Tcl Source Code

Check-in Differences
Login

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

Difference From core-8-5-branch To 0-day-21b0629c81

2024-04-12
22:58
merge 8.5 (minor backport from my core) simple speed-up if searching for the key from hash itself (i... check-in: 3307793b00 user: sebres tags: core-8-6-branch
22:55
minor backport from my core: simple speed-up if searching for the key from hash itself (it is safe t... Leaf check-in: f472941c43 user: sebres tags: core-8-5-branch
21:13
amend to [295b0570ff660950]: the bug was fixed incompletely, this is full bug fix now - don't allow ... check-in: 969a185ea4 user: sebres tags: core-8-5-branch
2018-08-29
14:45
closes [21b0629c81] 0-day vulnerability - insufficient escape by exec of batch-files for windows check-in: 99af12fd19 user: sebres tags: core-8-5-branch
2018-08-23
10:26
code review, skip slow test winpipe-8.2 executed args from injectList particularly (normally winpipe... Closed-Leaf check-in: 7f273d6639 user: sebres tags: 0-day-21b0629c81
08:00
code review, restored backwards compatibility of the simplest escape of quote-chars (so reverted sev... check-in: 897a17c523 user: sebres tags: 0-day-21b0629c81

Changes to .fossil-settings/binary-glob.

1
2
3
4
5
6
7
8
9
10
11
12
*.a
*.bmp
*.dll
*.exe
*.gif
*.gz
*.jpg
*.lib
*.pdf
*.png
*.xlsx
*.zip
<

<
<

<
<
<
<

<
<

1


2




3



*.bmp


*.gif




*.png


Deleted .fossil-settings/crlf-glob.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
compat/zlib/contrib/vstudio/readme.txt
compat/zlib/contrib/vstudio/*/zlib.rc
compat/zlib/contrib/vstudio/*/*.sln
compat/zlib/win32/*.txt
compat/zlib/win64/*.txt
libtommath/*.dsp
libtommath/*.sln
libtommath/*.vcproj
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.vc
win/rules.vc
win/rules-ext.vc
win/targets.vc
win/tcl.dsp
win/tcl.dsw
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































Added .fossil-settings/crnl-glob.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
tools/tcl.hpj.in
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.bc
win/makefile.vc
win/rules.vc
win/tcl.dsp
win/tcl.dsw
win/tcl.hpj.in

Changes to .fossil-settings/ignore-glob.

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
*.a
*.dll
*.dylib
*.dylib.E
*.exe
*.exp
*.la
*.lib
*.lo
*.o
*.obj
*.pdb
*.res
*.sl
*.so
*/Makefile
*/autom4te.cache
*/config.cache
*/config.log
*/config.status
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl*.zip
*/tclUuid.h
html
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
libtommath/*.pl
libtommath/*.sh
libtommath/doc/*
libtommath/tombc/*
libtommath/pre_gen/*
libtommath/pics/*
libtommath/mtest/*
libtommath/logs/*
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker
unix/dltest/*.bundle
unix/dltest/*.dll
unix/dltest/*.dylib
unix/dltest/*.o
unix/dltest/*.sl
unix/dltest/*.so
unix/tcl.pc
unix/tclIndex
unix/Tcl-Info.plist
unix/Tclsh-Info.plist
unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest
win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt



<


<

<







<








<
<
<





<



<









<


<
<
<
<
<
<


<
<



<

<

<

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
*.a
*.dll
*.dylib

*.exe
*.exp

*.lib

*.o
*.obj
*.pdb
*.res
*.sl
*.so
*/Makefile

*/config.cache
*/config.log
*/config.status
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc



html
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src

libtommath/*.pdf
libtommath/*.pl
libtommath/*.sh

libtommath/tombc/*
libtommath/pre_gen/*
libtommath/pics/*
libtommath/mtest/*
libtommath/logs/*
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex

unix/autoMkindex.tcl
unix/dltest.marker






unix/tcl.pc
unix/tclIndex


unix/pkgs/*
win/Debug*
win/Release*

win/pkgs/*

win/tcl.hpj

win/nmhlp-out.txt

Deleted .fossil-settings/manifest.

1
u
<


Deleted .gitattributes.

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
# Set the default behavior, in case people don't have core.autocrlf set.
* eol=lf
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.3 text
*.c text
*.css text
*.enc text
*.h text
*.htm text
*.html text
*.java text
*.js text
*.json text
*.n text
*.svg text
*.ts text
*.tcl text
*.test text

# Declare files that will always have CRLF line endings on checkout.
*.bat eol=crlf
*.sln eol=crlf
*.vc eol=crlf

# Denote all files that are truly binary and should not be modified.
*.a binary
*.bmp binary
*.dll binary
*.exe binary
*.gif binary
*.gz binary
*.jpg binary
*.lib binary
*.pdf binary
*.png binary
*.xlsx binary
*.zip binary
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































Deleted .gitignore.

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
*.a
*.bundle
*.dll
*.dylib
*.dylib.E
*.exe
*.exp
*.lib
*.o
*.obj
*.pdb
*.res
*.sl
*.so
.fslckout
Makefile
Tcl-Info.plist
Tclsh-Info.plist
autom4te.cache
config.cache
config.log
config.status
config.status.lineno
html
manifest.uuid
_FOSSIL_
*/tclConfig.sh
*/tclsh*
*/tcltest
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl*.zip
*/tclUuid.h
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
libtommath/*.pl
libtommath/*.sh
libtommath/doc/*
libtommath/tombc/*
libtommath/pre_gen/*
libtommath/pics/*
libtommath/mtest/*
libtommath/logs/*
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker
unix/tcl.pc
unix/tclIndex
unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest
win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































Changes to ChangeLog.

1
2
3
4
5
6
7
8
9
10
A NOTE ON THE CHANGELOG:
Starting in early 2011, Tcl source code has been under the management of
fossil, hosted at https://core.tcl-lang.org/tcl/ .  Fossil presents a "Timeline"
view of changes made that is superior in every way to a hand edited log file.
Because of this, many Tcl developers are now out of the habit of maintaining
this log file.  You may still find useful things in it, but the Timeline is
a better first place to look now.
============================================================================

2013-08-30  Don Porter  <[email protected]>


|







1
2
3
4
5
6
7
8
9
10
A NOTE ON THE CHANGELOG:
Starting in early 2011, Tcl source code has been under the management of
fossil, hosted at http://core.tcl.tk/tcl/ .  Fossil presents a "Timeline"
view of changes made that is superior in every way to a hand edited log file.
Because of this, many Tcl developers are now out of the habit of maintaining
this log file.  You may still find useful things in it, but the Timeline is
a better first place to look now.
============================================================================

2013-08-30  Don Porter  <[email protected]>
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
	before calls demanding them.  [Bug 3479689]: Stop memory corruption
	when shimmering 0-refCount value to "path" type.

2012-01-22  Jan Nijtmans  <[email protected]>

	* tools/uniClass.tcl:    [FRQ 3473670]: Various Unicode-related
	* tools/uniParse.tcl:    speedups/robustness. Enhanced tools to be
	* generic/tclUniData.c:  able to handle characters > 0xFFFF. Done in
	* generic/tclUtf.c:      all branches in order to simplify merges for
	* generic/regc_locale.c: new Unicode versions (such as 6.1)

2012-01-22  Donal K. Fellows  <[email protected]>

	* generic/tclDictObj.c (DictExistsCmd): [Bug 3475264]: Ensure that
	errors only ever happen when insufficient arguments are supplied, and







|







1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
	before calls demanding them.  [Bug 3479689]: Stop memory corruption
	when shimmering 0-refCount value to "path" type.

2012-01-22  Jan Nijtmans  <[email protected]>

	* tools/uniClass.tcl:    [FRQ 3473670]: Various Unicode-related
	* tools/uniParse.tcl:    speedups/robustness. Enhanced tools to be
	* generic/tclUniData.c:  able to handle characters > 0xffff. Done in
	* generic/tclUtf.c:      all branches in order to simplify merges for
	* generic/regc_locale.c: new Unicode versions (such as 6.1)

2012-01-22  Donal K. Fellows  <[email protected]>

	* generic/tclDictObj.c (DictExistsCmd): [Bug 3475264]: Ensure that
	errors only ever happen when insufficient arguments are supplied, and

Changes to ChangeLog.2005.

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923

	* generic/tclInt.h (TclGetTruthValueFromObj):	New routine.
	* generic/tclExecute.c:	Updated callers to call new routine.
	* generic/tclBasic.c:	Updated callers to call new routine.
	* generic/tclCompCmds.c:	Updated callers to call new routine.
	* generic/tclDictObj.c:	Updated callers to call new routine.
	* tests/obj.test:	Corrected bad tests that actually expected
	values like "47" and "0xAC" to be accepted as booleans.

	* generic/tclLiteral.c: Disabled the code that forces some literals
	into the "int" Tcl_ObjType during registration. We can re-enable it if
	this change causes trouble, but it seems more sensible to let Tcl's
	"on-demand" shimmering rule, and not try to pre-guess things.

2005-04-20  Kevin B. Kenny  <[email protected]>







|







2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923

	* generic/tclInt.h (TclGetTruthValueFromObj):	New routine.
	* generic/tclExecute.c:	Updated callers to call new routine.
	* generic/tclBasic.c:	Updated callers to call new routine.
	* generic/tclCompCmds.c:	Updated callers to call new routine.
	* generic/tclDictObj.c:	Updated callers to call new routine.
	* tests/obj.test:	Corrected bad tests that actually expected
	values like "47" and "0xac" to be accepted as booleans.

	* generic/tclLiteral.c: Disabled the code that forces some literals
	into the "int" Tcl_ObjType during registration. We can re-enable it if
	this change causes trouble, but it seems more sensible to let Tcl's
	"on-demand" shimmering rule, and not try to pre-guess things.

2005-04-20  Kevin B. Kenny  <[email protected]>

Added README.



















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
README:  Tcl
    This is the Tcl 8.5.19 source distribution.
	http://sourceforge.net/projects/tcl/files/Tcl/
    You can get any source release of Tcl from the URL above.

Contents
--------
    1. Introduction
    2. Documentation
    3. Compiling and installing Tcl
    4. Development tools
    5. Tcl newsgroup
    6. The Tcler's Wiki
    7. Mailing lists
    8. Support and Training
    9. Tracking Development
    10. Thank You

1. Introduction
---------------
Tcl provides a powerful platform for creating integration applications that
tie together diverse applications, protocols, devices, and frameworks.
When paired with the Tk toolkit, Tcl provides the fastest and most powerful
way to create GUI applications that run on PCs, Unix, and Mac OS X.
Tcl can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.

Tcl is maintained, enhanced, and distributed freely by the Tcl community.
Source code development and tracking of bug reports and feature requests
takes place at:

	http://core.tcl.tk/

Tcl/Tk release and mailing list services are hosted by SourceForge:

	http://sourceforge.net/projects/tcl/

with the Tcl Developer Xchange hosted at:

	http://www.tcl.tk/

Tcl is a freely available open source package.  You can do virtually
anything you like with it, such as modifying it, redistributing it,
and selling it either in whole or in part.  See the file
"license.terms" for complete information.

2. Documentation
----------------

Extensive documentation is available at our website.
The home page for this release, including new features, is
	http://www.tcl.tk/software/tcltk/8.5.html

Detailed release notes can be found at the file distributions page
by clicking on the relevant version.
	http://sourceforge.net/projects/tcl/files/Tcl/

Information about Tcl itself can be found at
	http://www.tcl.tk/about/

There have been many Tcl books on the market.  Many are mentioned in the Wiki:
	http://wiki.tcl.tk/_/ref?N=25206

To view the complete set of reference manual entries for Tcl 8.5 online,
visit the URL:
	http://www.tcl.tk/man/tcl8.5/

2a. Unix Documentation
----------------------

The "doc" subdirectory in this release contains a complete set of
reference manual entries for Tcl.  Files with extension ".1" are for
programs (for example, tclsh.1); files with extension ".3" are for C
library procedures; and files with extension ".n" describe Tcl
commands.  The file "doc/Tcl.n" gives a quick summary of the Tcl
language syntax.  To print any of the man pages on Unix, cd to the
"doc" directory and invoke your favorite variant of troff using the
normal -man macros, for example

		ditroff -man Tcl.n

to print Tcl.n.  If Tcl has been installed correctly and your "man" program
supports it, you should be able to access the Tcl manual entries using the
normal "man" mechanisms, such as

		man Tcl

2b. Windows Documentation
-------------------------

The "doc" subdirectory in this release contains a complete set of Windows
help files for Tcl.  Once you install this Tcl release, a shortcut to the
Windows help Tcl documentation will appear in the "Start" menu:

	Start | Programs | Tcl | Tcl Help

3. Compiling and installing Tcl
-------------------------------

There are brief notes in the unix/README, win/README, and macosx/README about
compiling on these different platforms.  There is additional information
about building Tcl from sources at

	http://www.tcl.tk/doc/howto/compile.html

4. Development tools
---------------------------

ActiveState produces a high quality set of commercial quality development
tools that is available to accelerate your Tcl application development.
Tcl Dev Kit builds on the earlier TclPro toolset and provides a debugger,
static code checker, single-file wrapping utility, bytecode compiler and
more.  More information can be found at

	http://www.ActiveState.com/Tcl

5. Tcl newsgroup
----------------

There is a USENET news group, "comp.lang.tcl", intended for the exchange of
information about Tcl, Tk, and related applications.  The newsgroup is a
great place to ask general information questions.  For bug reports, please
see the "Support and bug fixes" section below.

6. Tcl'ers Wiki
---------------

A Wiki-based open community site covering all aspects of Tcl/Tk is at:

	http://wiki.tcl.tk/

It is dedicated to the Tcl programming language and its extensions.  A
wealth of useful information can be found there.  It contains code
snippets, references to papers, books, and FAQs, as well as pointers to
development tools, extensions, and applications.  You can also recommend
additional URLs by editing the wiki yourself.

7. Mailing lists
----------------

Several mailing lists are hosted at SourceForge to discuss development or
use issues (like Macintosh and Windows topics).  For more information and
to subscribe, visit:

	http://sourceforge.net/projects/tcl/

and go to the Mailing Lists page.

8. Support and Training
------------------------

We are very interested in receiving bug reports, patches, and suggestions
for improvements.  We prefer that you send this information to us as
tickets entered into our tracker at:

	http://core.tcl.tk/tcl/reportlist

We will log and follow-up on each bug, although we cannot promise a
specific turn-around time.  Enhancements may take longer and may not happen
at all unless there is widespread support for them (we're trying to
slow the rate at which Tcl/Tk turns into a kitchen sink).  It's very
difficult to make incompatible changes to Tcl/Tk at this point, due to
the size of the installed base.

The Tcl community is too large for us to provide much individual support
for users.  If you need help we suggest that you post questions to
comp.lang.tcl.  We read the newsgroup and will attempt to answer esoteric
questions for which no one else is likely to know the answer.  In addition,
see the following Web site for links to other organizations that offer
Tcl/Tk training:

	http://wiki.tcl.tk/training

9. Tracking Development
-----------------------

Tcl is developed in public.  To keep an eye on how Tcl is changing, see
	http://core.tcl.tk/

10. Thank You
-------------

We'd like to express our thanks to the Tcl community for all the
helpful suggestions, bug reports, and patches we have received.
Tcl/Tk has improved vastly and will continue to do so with your help.

Deleted README.md.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# README:  Tcl

This is the **Tcl 8.5.19** source distribution.

You can get any source release of Tcl from [our distribution
site](https://sourceforge.net/projects/tcl/files/Tcl/).

[![Build Status](https://github.com/tcltk/tcl/workflows/Linux/badge.svg?branch=core-8-5-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Linux%22+branch%3Acore-8-5-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/Windows/badge.svg?branch=core-8-5-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Windows%22+branch%3Acore-8-5-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/macOS/badge.svg?branch=core-8-5-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22macOS%22+branch%3Acore-8-5-branch)

## Contents
 1. [Introduction](#intro)
 2. [Documentation](#doc)
 3. [Compiling and installing Tcl](#build)
 4. [Development tools](#devtools)
 5. [Tcl newsgroup](#complangtcl)
 6. [The Tcler's Wiki](#wiki)
 7. [Mailing lists](#email)
 8. [Support and Training](#support)
 9. [Tracking Development](#watch)
 10. [Thank You](#thanks)

## <a id="intro">1.</a> Introduction
Tcl provides a powerful platform for creating integration applications that
tie together diverse applications, protocols, devices, and frameworks.
When paired with the Tk toolkit, Tcl provides the fastest and most powerful
way to create GUI applications that run on PCs, Unix, and Mac OS X.
Tcl can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.

Tcl is maintained, enhanced, and distributed freely by the Tcl community.
Source code development and tracking of bug reports and feature requests
takes place at [core.tcl-lang.org](https://core.tcl-lang.org/).
Tcl/Tk release and mailing list services are [hosted by
SourceForge](https://sourceforge.net/projects/tcl/)
with the Tcl Developer Xchange hosted at
[www.tcl-lang.org](https://www.tcl-lang.org).

Tcl is a freely available open source package.  You can do virtually
anything you like with it, such as modifying it, redistributing it,
and selling it either in whole or in part.  See the file
`license.terms` for complete information.

## <a id="doc">2.</a> Documentation
Extensive documentation is available at our website.
The home page for this release, including new features, is
[here](https://www.tcl.tk/software/tcltk/8.5.html).
Detailed release notes can be found at the
[file distributions page](https://sourceforge.net/projects/tcl/files/Tcl/)
by clicking on the relevant version.

Information about Tcl itself can be found at the [Developer
Xchange](https://www.tcl-lang.org/about/).
There have been many Tcl books on the market.  Many are mentioned in
[the Wiki](https://wiki.tcl-lang.org/_/ref?N=25206).

The complete set of reference manual entries for Tcl 8.5 is [online,
here](https://www.tcl-lang.org/man/tcl8.5/).

### <a id="doc.unix">2a.</a> Unix Documentation
The `doc` subdirectory in this release contains a complete set of
reference manual entries for Tcl.  Files with extension "`.1`" are for
programs (for example, `tclsh.1`); files with extension "`.3`" are for C
library procedures; and files with extension "`.n`" describe Tcl
commands.  The file "`doc/Tcl.n`" gives a quick summary of the Tcl
language syntax.  To print any of the man pages on Unix, cd to the
"doc" directory and invoke your favorite variant of troff using the
normal -man macros, for example

		groff -man -Tpdf Tcl.n >output.pdf

to print Tcl.n to PDF.  If Tcl has been installed correctly and your "man" program
supports it, you should be able to access the Tcl manual entries using the
normal "man" mechanisms, such as

		man Tcl

### <a id="doc.win">2b.</a> Windows Documentation
The "doc" subdirectory in this release contains a complete set of Windows
help files for Tcl.  Once you install this Tcl release, a shortcut to the
Windows help Tcl documentation will appear in the "Start" menu:

		Start | Programs | Tcl | Tcl Help

## <a id="build">3.</a> Compiling and installing Tcl
There are brief notes in the `unix/README`, `win/README`, and `macosx/README`
about compiling on these different platforms.  There is additional information
about building Tcl from sources
[online](https://www.tcl-lang.org/doc/howto/compile.html).

## <a id="devtools">4.</a> Development tools
ActiveState produces a high quality set of commercial quality development
tools that is available to accelerate your Tcl application development.
Tcl Dev Kit builds on the earlier TclPro toolset and provides a debugger,
static code checker, single-file wrapping utility, bytecode compiler and
more.  More information can be found at

	http://www.ActiveState.com/Tcl

## <a id="complangtcl">5.</a> Tcl newsgroup
There is a USENET news group, "`comp.lang.tcl`", intended for the exchange of
information about Tcl, Tk, and related applications.  The newsgroup is a
great place to ask general information questions.  For bug reports, please
see the "Support and bug fixes" section below.

## <a id="wiki">6.</a> Tcl'ers Wiki
There is a [wiki-based open community site](https://wiki.tcl-lang.org/)
covering all aspects of Tcl/Tk.

It is dedicated to the Tcl programming language and its extensions.  A
wealth of useful information can be found there.  It contains code
snippets, references to papers, books, and FAQs, as well as pointers to
development tools, extensions, and applications.  You can also recommend
additional URLs by editing the wiki yourself.

## <a id="email">7.</a> Mailing lists
Several mailing lists are hosted at SourceForge to discuss development or use
issues (like Macintosh and Windows topics).  For more information and to
subscribe, visit [here](https://sourceforge.net/projects/tcl/) and go to the
Mailing Lists page.

## <a id="support">8.</a> Support and Training
We are very interested in receiving bug reports, patches, and suggestions for
improvements.  We prefer that you send this information to us as tickets
entered into [our issue tracker](https://core.tcl-lang.org/tcl/reportlist).

We will log and follow-up on each bug, although we cannot promise a
specific turn-around time.  Enhancements may take longer and may not happen
at all unless there is widespread support for them (we're trying to
slow the rate at which Tcl/Tk turns into a kitchen sink).  It's very
difficult to make incompatible changes to Tcl/Tk at this point, due to
the size of the installed base.

The Tcl community is too large for us to provide much individual support for
users.  If you need help we suggest that you post questions to `comp.lang.tcl`
or ask a question on [Stack
Overflow](https://stackoverflow.com/questions/tagged/tcl).  We read the
newsgroup and will attempt to answer esoteric questions for which no one else
is likely to know the answer.  In addition, see the wiki for [links to other
organizations](https://wiki.tcl-lang.org/training) that offer Tcl/Tk training.

## <a id="watch">9.</a> Tracking Development
Tcl is developed in public.  You can keep an eye on how Tcl is changing at
[core.tcl-lang.org](https://core.tcl-lang.org/).

## <a id="thanks">10.</a> Thank You
We'd like to express our thanks to the Tcl community for all the
helpful suggestions, bug reports, and patches we have received.
Tcl/Tk has improved vastly and will continue to do so with your help.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































































































































Changes to changes.

2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
existing files. (JH)

9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect
to the standard channel, do not increment the refcount. The channel can
be NULL if there is for example no standard input. (JL)

9/6/96 (portability improvement) Changed parsing of backslash sequences
like \n to translate directly to absolute values like 0xA instead of
letting the compiler do the translation.  This guarantees that the
translation is done the same everywhere. (JO)

9/9/96 (bug fix) If channel is opened and not associated with any
interpreter, but Tcl decides to use it as one of the standard channels, it
became impossible to close the channel with Tcl_Close -- instead you had
to call Tcl_UnregisterChannel. Fixed now so that it's safe to call







|







2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
existing files. (JH)

9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect
to the standard channel, do not increment the refcount. The channel can
be NULL if there is for example no standard input. (JL)

9/6/96 (portability improvement) Changed parsing of backslash sequences
like \n to translate directly to absolute values like 0xa instead of
letting the compiler do the translation.  This guarantees that the
translation is done the same everywhere. (JO)

9/9/96 (bug fix) If channel is opened and not associated with any
interpreter, but Tcl decides to use it as one of the standard channels, it
became impossible to close the channel with Tcl_Close -- instead you had
to call Tcl_UnregisterChannel. Fixed now so that it's safe to call
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800

2013-09-07 (bug fix) stop crashes in tclcompiler (kupries,porter)

2013-09-07 (bug fix)[86ceb4] have tm path favor first provider (neumann,porter)

2013-09-13 (bug fix)[bdd91c] crash in exec stack mem management (azazel)

--- Released 8.5.15, September 16, 2013 --- https://core.tcl-lang.org/tcl/ for details

2013-09-19 (bug fix)[3487626] segfaults in [dict] compilers (porter)

2013-09-19 (bug fix) [info frame] line OBOEs in bytecode (porter)

2013-09-25 (bug fix)[d614d63] namespace matching *:: deletion fail (fellows)








|







7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800

2013-09-07 (bug fix) stop crashes in tclcompiler (kupries,porter)

2013-09-07 (bug fix)[86ceb4] have tm path favor first provider (neumann,porter)

2013-09-13 (bug fix)[bdd91c] crash in exec stack mem management (azazel)

--- Released 8.5.15, September 16, 2013 --- http://core.tcl.tk/tcl/ for details

2013-09-19 (bug fix)[3487626] segfaults in [dict] compilers (porter)

2013-09-19 (bug fix) [info frame] line OBOEs in bytecode (porter)

2013-09-25 (bug fix)[d614d63] namespace matching *:: deletion fail (fellows)

7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
	*** POTENTIAL INCOMPATIBILITY ***

2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries)
=> platform 1.0.13

2014-08-12 tzdata updated to Olson's tzdata2014f (kenny)

--- Released 8.5.16, August 25, 2014 --- https://core.tcl-lang.org/tcl/ for details

2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter)

2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)

2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)

2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)

2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter)

--- Released 8.5.17, October 25, 2014 --- https://core.tcl-lang.org/tcl/ for details

2014-10-26 Support for Windows 10 (nijtmans)

2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans)

2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter)








|











|







7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
	*** POTENTIAL INCOMPATIBILITY ***

2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries)
=> platform 1.0.13

2014-08-12 tzdata updated to Olson's tzdata2014f (kenny)

--- Released 8.5.16, August 25, 2014 --- http://core.tcl.tk/tcl/ for details

2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter)

2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)

2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)

2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)

2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter)

--- Released 8.5.17, October 25, 2014 --- http://core.tcl.tk/tcl/ for details

2014-10-26 Support for Windows 10 (nijtmans)

2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans)

2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter)

7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938

2015-01-29 (bug) Stop crashes when extension var resolvers misbehave (porter)

2015-02-05 (bug) Plug stacked channel memleak (porter)

2015-02-11 tzdata updated to Olson's tzdata2015a (venkat)

--- Released 8.5.18, March 6, 2015 --- https://core.tcl-lang.org/tcl/ for details

2015-03-10 (bug)[3028676] Refinement in OS X notifier (steffen,walzer,lars_h)

2015-04-23 (bug)[19ea02] Win: shared read from linked dirs (bogdan,oehhar)

2015-04-24 (bug)[879a07] Incomplete chars @ buffer ends (leunissen,porter)








|







7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938

2015-01-29 (bug) Stop crashes when extension var resolvers misbehave (porter)

2015-02-05 (bug) Plug stacked channel memleak (porter)

2015-02-11 tzdata updated to Olson's tzdata2015a (venkat)

--- Released 8.5.18, March 6, 2015 --- http://core.tcl.tk/tcl/ for details

2015-03-10 (bug)[3028676] Refinement in OS X notifier (steffen,walzer,lars_h)

2015-04-23 (bug)[19ea02] Win: shared read from linked dirs (bogdan,oehhar)

2015-04-24 (bug)[879a07] Incomplete chars @ buffer ends (leunissen,porter)

7973
7974
7975
7976
7977
7978
7979
7980

2015-11-20 (bug)[40f628] ListObjReplace callers fail to detect max (porter)

2015-12-11 (bug)[c9eb6b] tolerate unset ::env(TZ) (gahr, nijtmans)

2016-01-29 (TIP 440) tcl_platform(engine) -- Tcl implementation (mistachkin)

--- Released 8.5.19, February 12, 2016 --- https://core.tcl-lang.org/tcl/ for details







|
7973
7974
7975
7976
7977
7978
7979
7980

2015-11-20 (bug)[40f628] ListObjReplace callers fail to detect max (porter)

2015-12-11 (bug)[c9eb6b] tolerate unset ::env(TZ) (gahr, nijtmans)

2016-01-29 (TIP 440) tcl_platform(engine) -- Tcl implementation (mistachkin)

--- Released 8.5.19, February 12, 2016 --- http://core.tcl.tk/tcl/ for details

Changes to compat/fixstrtod.c.

1
2
3
4
5
6
7
8
/*
 * fixstrtod.c --
 *
 *	Source code for the "fixstrtod" procedure.  This procedure is
 *	used in place of strtod under Solaris 2.4, in order to fix
 *	a bug where the "end" pointer gets set incorrectly.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
|







1
2
3
4
5
6
7
8
/* 
 * fixstrtod.c --
 *
 *	Source code for the "fixstrtod" procedure.  This procedure is
 *	used in place of strtod under Solaris 2.4, in order to fix
 *	a bug where the "end" pointer gets set incorrectly.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.

Changes to compat/gettod.c.

1
2
3
4
5
6
7
8
/*
 * gettod.c --
 *
 *	This file provides the gettimeofday function on systems
 *	that only have the System V ftime function.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
|







1
2
3
4
5
6
7
8
/* 
 * gettod.c --
 *
 *	This file provides the gettimeofday function on systems
 *	that only have the System V ftime function.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

int
gettimeofday(
    struct timeval *tp,
    struct timezone *tz)
{
    struct timeb t;
    (void)tz;

    ftime(&t);
    tp->tv_sec = t.time;
    tp->tv_usec = t.millitm * 1000;
    return 0;
}








<



|



17
18
19
20
21
22
23

24
25
26
27
28
29
30

int
gettimeofday(
    struct timeval *tp,
    struct timezone *tz)
{
    struct timeb t;


    ftime(&t);
    tp->tv_sec = t.time;
    tp->tv_usec = t. millitm * 1000;
    return 0;
}

Changes to compat/memcmp.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#include "tclPort.h"

/*
 * Here is the prototype just in case it is not included in tclPort.h.
 */

int		memcmp(const void *s1, const void *s2, size_t n);

/*
 *----------------------------------------------------------------------
 *
 * memcmp --
 *
 *	Compares two bytes sequences.







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#include "tclPort.h"

/*
 * Here is the prototype just in case it is not included in tclPort.h.
 */

int		memcmp(CONST VOID *s1, CONST VOID *s2, size_t n);

/*
 *----------------------------------------------------------------------
 *
 * memcmp --
 *
 *	Compares two bytes sequences.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
memcmp(
    const void *s1,		/* First string. */
    const void *s2,		/* Second string. */
    size_t n)			/* Length to compare. */
{
    const unsigned char *ptr1 = (const unsigned char *) s1;
    const unsigned char *ptr2 = (const unsigned char *) s2;

    for ( ; n-- ; ptr1++, ptr2++) {
	unsigned char u1 = *ptr1, u2 = *ptr2;

	if (u1 != u2) {
	    return (u1-u2);
	}







|
|


|
|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
memcmp(
    CONST VOID *s1,		/* First string. */
    CONST VOID *s2,		/* Second string. */
    size_t n)			/* Length to compare. */
{
    CONST unsigned char *ptr1 = (CONST unsigned char *) s1;
    CONST unsigned char *ptr2 = (CONST unsigned char *) s2;

    for ( ; n-- ; ptr1++, ptr2++) {
	unsigned char u1 = *ptr1, u2 = *ptr2;

	if (u1 != u2) {
	    return (u1-u2);
	}

Changes to compat/opendir.c.

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
/*
 * opendir.c --
 *
 *	This file provides dirent-style directory-reading procedures for V7
 *	Unix systems that don't have such procedures. The origin of this code
 *	is unclear, but it seems to have come originally from Larry Wall.
 */

#include "tclInt.h"

#undef DIRSIZ
#define DIRSIZ(dp) \
    ((sizeof(struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

/*
 * open a directory.
 */

DIR *
opendir(
    char *name)
{
    DIR *dirp;
    int fd;
    const char *myname;

    myname = ((*name == '\0') ? "." : name);
    if ((fd = open(myname, 0, 0)) == -1) {
	return NULL;
    }
    dirp = (DIR *) ckalloc(sizeof(DIR));
    if (dirp == NULL) {
|











|









|
|
|







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
/* 
 * opendir.c --
 *
 *	This file provides dirent-style directory-reading procedures for V7
 *	Unix systems that don't have such procedures. The origin of this code
 *	is unclear, but it seems to have come originally from Larry Wall.
 */

#include "tclInt.h"

#undef DIRSIZ
#define DIRSIZ(dp) \
    ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

/*
 * open a directory.
 */

DIR *
opendir(
    char *name)
{
    register DIR *dirp;
    register int fd;
    char *myname;

    myname = ((*name == '\0') ? "." : name);
    if ((fd = open(myname, 0, 0)) == -1) {
	return NULL;
    }
    dirp = (DIR *) ckalloc(sizeof(DIR));
    if (dirp == NULL) {
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

/*
 * read an old style directory entry and present it as a new one
 */
#ifndef pyr
#define	ODIRSIZ	14

struct olddirect {
    ino_t od_ino;
    char od_name[ODIRSIZ];
};
#else	/* a Pyramid in the ATT universe */
#define	ODIRSIZ	248

struct olddirect {
    long od_ino;
    short od_fill1, od_fill2;
    char od_name[ODIRSIZ];
};
#endif

/*
 * get next entry in a directory.
 */

struct dirent *
readdir(
    DIR *dirp)
{
    struct olddirect *dp;
    static struct dirent dir;

    for (;;) {
	if (dirp->dd_loc == 0) {
	    dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
	    if (dirp->dd_size <= 0) {
		return NULL;







|






|












|

|







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

/*
 * read an old style directory entry and present it as a new one
 */
#ifndef pyr
#define	ODIRSIZ	14

struct	olddirect {
    ino_t od_ino;
    char od_name[ODIRSIZ];
};
#else	/* a Pyramid in the ATT universe */
#define	ODIRSIZ	248

struct	olddirect {
    long od_ino;
    short od_fill1, od_fill2;
    char od_name[ODIRSIZ];
};
#endif

/*
 * get next entry in a directory.
 */

struct dirent *
readdir(
    register DIR *dirp)
{
    register struct olddirect *dp;
    static struct dirent dir;

    for (;;) {
	if (dirp->dd_loc == 0) {
	    dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
	    if (dirp->dd_size <= 0) {
		return NULL;
97
98
99
100
101
102
103
104
105
106
107
108
109
110

/*
 * close a directory.
 */

void
closedir(
    DIR *dirp)
{
    close(dirp->dd_fd);
    dirp->dd_fd = -1;
    dirp->dd_loc = 0;
    ckfree(dirp);
}







|




|

97
98
99
100
101
102
103
104
105
106
107
108
109
110

/*
 * close a directory.
 */

void
closedir(
    register DIR *dirp)
{
    close(dirp->dd_fd);
    dirp->dd_fd = -1;
    dirp->dd_loc = 0;
    ckfree((char *) dirp);
}

Changes to compat/strncasecmp.c.

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
/*
 * strncasecmp.c --
 *
 *	Source code for the "strncasecmp" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclPort.h"

/*
 * This array is designed for mapping upper and lower case letter together for
 * a case independent comparison. The mappings are based upon ASCII character
 * sequences.
 */

static const unsigned char charmap[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|



















|







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
/* 
 * strncasecmp.c --
 *
 *	Source code for the "strncasecmp" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclPort.h"

/*
 * This array is designed for mapping upper and lower case letter together for
 * a case independent comparison. The mappings are based upon ASCII character
 * sequences.
 */

static unsigned char charmap[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
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
    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};

/*
 * Here are the prototypes just in case they are not included in tclPort.h.
 */

int		strncasecmp(const char *s1, const char *s2, size_t n);
int		strcasecmp(const char *s1, const char *s2);

/*
 *----------------------------------------------------------------------
 *
 * strcasecmp --
 *
 *	Compares two strings, ignoring case differences.
 *
 * Results:
 *	Compares two null-terminated strings s1 and s2, returning -1, 0, or 1
 *	if s1 is lexicographically less than, equal to, or greater than s2.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
strcasecmp(
    const char *s1,		/* First string. */
    const char *s2)		/* Second string. */
{
    unsigned char u1, u2;

    for ( ; ; s1++, s2++) {
	u1 = (unsigned char) *s1;
	u2 = (unsigned char) *s2;
	if ((u1 == '\0') || (charmap[u1] != charmap[u2])) {







|
|




















|
|







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
    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};

/*
 * Here are the prototypes just in case they are not included in tclPort.h.
 */

int		strncasecmp(CONST char *s1, CONST char *s2, size_t n);
int		strcasecmp(CONST char *s1, CONST char *s2);

/*
 *----------------------------------------------------------------------
 *
 * strcasecmp --
 *
 *	Compares two strings, ignoring case differences.
 *
 * Results:
 *	Compares two null-terminated strings s1 and s2, returning -1, 0, or 1
 *	if s1 is lexicographically less than, equal to, or greater than s2.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
strcasecmp(
    CONST char *s1,		/* First string. */
    CONST char *s2)		/* Second string. */
{
    unsigned char u1, u2;

    for ( ; ; s1++, s2++) {
	u1 = (unsigned char) *s1;
	u2 = (unsigned char) *s2;
	if ((u1 == '\0') || (charmap[u1] != charmap[u2])) {
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
strncasecmp(
    const char *s1,		/* First string. */
    const char *s2,		/* Second string. */
    size_t length)		/* Maximum number of characters to compare
				 * (stop earlier if the end of either string
				 * is reached). */
{
    unsigned char u1, u2;

    for (; length != 0; length--, s1++, s2++) {







|
|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
strncasecmp(
    CONST char *s1,		/* First string. */
    CONST char *s2,		/* Second string. */
    size_t length)		/* Maximum number of characters to compare
				 * (stop earlier if the end of either string
				 * is reached). */
{
    unsigned char u1, u2;

    for (; length != 0; length--, s1++, s2++) {

Changes to compat/strstr.c.

1
2
3
4
5
6
7
8
/*
 * strstr.c --
 *
 *	Source code for the "strstr" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
|







1
2
3
4
5
6
7
8
/* 
 * strstr.c --
 *
 *	Source code for the "strstr" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
strstr(
    const char *string,		/* String to search. */
    const char *substring)		/* Substring to try to find in string. */
{
    const char *a, *b;

    /*
     * First scan quickly through the two strings looking for a
     * single-character match. When it's found, then compare the rest of the
     * substring.
     */

    b = substring;
    if (*b == 0) {
	return (char *)string;
    }
    for ( ; *string != 0; string += 1) {
	if (*string != *b) {
	    continue;
	}
	a = string;
	while (1) {
	    if (*b == 0) {
		return (char *)string;
	    }
	    if (*a++ != *b++) {
		break;
	    }
	}
	b = substring;
    }
    return NULL;
}







|
|

|









|








|









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
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
strstr(
    register char *string,	/* String to search. */
    char *substring)		/* Substring to try to find in string. */
{
    register char *a, *b;

    /*
     * First scan quickly through the two strings looking for a
     * single-character match. When it's found, then compare the rest of the
     * substring.
     */

    b = substring;
    if (*b == 0) {
	return string;
    }
    for ( ; *string != 0; string += 1) {
	if (*string != *b) {
	    continue;
	}
	a = string;
	while (1) {
	    if (*b == 0) {
		return string;
	    }
	    if (*a++ != *b++) {
		break;
	    }
	}
	b = substring;
    }
    return NULL;
}

Changes to compat/strtod.c.

1
2
3
4
5
6
7
8
/*
 * strtod.c --
 *
 *	Source code for the "strtod" library procedure.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
|







1
2
3
4
5
6
7
8
/* 
 * strtod.c --
 *
 *	Source code for the "strtod" library procedure.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
strtod(
    const char *string,		/* A decimal ASCII floating-point number,
				 * optionally preceded by white space. Must
				 * have form "-I.FE-X", where I is the integer
				 * part of the mantissa, F is the fractional
				 * part of the mantissa, and X is the
				 * exponent. Either of the signs may be "+",
				 * "-", or omitted. Either I or F may be
				 * omitted, or both. The decimal point isn't
				 * necessary unless F is present. The "E" may
				 * actually be an "e". E and X may both be
				 * omitted (but not just one). */
    char **endPtr)		/* If non-NULL, store terminating character's
				 * address here. */
{
    int sign, expSign = FALSE;
    double fraction, dblExp, *d;
    const char *p;
    int c;
    int exp = 0;		/* Exponent read from "EX" field. */
    int fracExp = 0;		/* Exponent that derives from the fractional
				 * part. Under normal circumstatnces, it is
				 * the negative of the number of digits in F.
				 * However, if I is very long, the last digits
				 * of I get dropped (otherwise a long I with a
				 * large negative exponent could cause an
				 * unnecessary overflow on I alone). In this
				 * case, fracExp is incremented one for each
				 * dropped digit. */
    int mantSize;		/* Number of digits in mantissa. */
    int decPt;			/* Number of mantissa digits BEFORE decimal
				 * point. */
    const char *pExp;		/* Temporarily holds location of exponent in
				 * string. */

    /*
     * Strip off leading blanks and check for a sign.
     */

    p = string;







|















|
|













|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
strtod(
    CONST char *string,		/* A decimal ASCII floating-point number,
				 * optionally preceded by white space. Must
				 * have form "-I.FE-X", where I is the integer
				 * part of the mantissa, F is the fractional
				 * part of the mantissa, and X is the
				 * exponent. Either of the signs may be "+",
				 * "-", or omitted. Either I or F may be
				 * omitted, or both. The decimal point isn't
				 * necessary unless F is present. The "E" may
				 * actually be an "e". E and X may both be
				 * omitted (but not just one). */
    char **endPtr)		/* If non-NULL, store terminating character's
				 * address here. */
{
    int sign, expSign = FALSE;
    double fraction, dblExp, *d;
    register CONST char *p;
    register int c;
    int exp = 0;		/* Exponent read from "EX" field. */
    int fracExp = 0;		/* Exponent that derives from the fractional
				 * part. Under normal circumstatnces, it is
				 * the negative of the number of digits in F.
				 * However, if I is very long, the last digits
				 * of I get dropped (otherwise a long I with a
				 * large negative exponent could cause an
				 * unnecessary overflow on I alone). In this
				 * case, fracExp is incremented one for each
				 * dropped digit. */
    int mantSize;		/* Number of digits in mantissa. */
    int decPt;			/* Number of mantissa digits BEFORE decimal
				 * point. */
    CONST char *pExp;		/* Temporarily holds location of exponent in
				 * string. */

    /*
     * Strip off leading blanks and check for a sign.
     */

    p = string;
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

    /*
     * Now suck up the digits in the mantissa. Use two integers to collect 9
     * digits each (this is faster than using floating-point). If the mantissa
     * has more than 18 digits, ignore the extras, since they can't affect the
     * value anyway.
     */

    pExp  = p;
    p -= mantSize;
    if (decPt < 0) {
	decPt = mantSize;
    } else {
	mantSize -= 1;		/* One of the digits was the point. */
    }







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

    /*
     * Now suck up the digits in the mantissa. Use two integers to collect 9
     * digits each (this is faster than using floating-point). If the mantissa
     * has more than 18 digits, ignore the extras, since they can't affect the
     * value anyway.
     */
    
    pExp  = p;
    p -= mantSize;
    if (decPt < 0) {
	decPt = mantSize;
    } else {
	mantSize -= 1;		/* One of the digits was the point. */
    }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    }

    /*
     * Generate a floating-point number that represents the exponent. Do this
     * by processing the exponent one bit at a time to combine many powers of
     * 2 of 10. Then combine the exponent with the fraction.
     */

    if (exp < 0) {
	expSign = TRUE;
	exp = -exp;
    } else {
	expSign = FALSE;
    }
    if (exp > maxExponent) {







|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    }

    /*
     * Generate a floating-point number that represents the exponent. Do this
     * by processing the exponent one bit at a time to combine many powers of
     * 2 of 10. Then combine the exponent with the fraction.
     */
    
    if (exp < 0) {
	expSign = TRUE;
	exp = -exp;
    } else {
	expSign = FALSE;
    }
    if (exp > maxExponent) {

Changes to compat/strtol.c.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
/*
 * strtol.c --
 *
 *	Source code for the "strtol" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */


#include "tclInt.h"

/*
 *----------------------------------------------------------------------
 *
 * strtol --
 *
|











>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 
 * strtol.c --
 *
 *	Source code for the "strtol" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <ctype.h>
#include "tclInt.h"

/*
 *----------------------------------------------------------------------
 *
 * strtol --
 *
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

long int
strtol(
    const char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion. Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    const char *p;
    long result;

    /*
     * Skip any leading blanks.
     */

    p = string;







|











|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

long int
strtol(
    CONST char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion. Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    register CONST char *p;
    long result;

    /*
     * Skip any leading blanks.
     */

    p = string;

Changes to compat/strtoul.c.

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
/*
 * strtoul.c --
 *
 *	Source code for the "strtoul" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The table below is used to convert from ASCII digits to a numerical
 * equivalent. It maps from '0' through 'z' to integers (100 for non-digit
 * characters).
 */

static const char cvtIn[] = {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,		/* '0' - '9' */
    100, 100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'A' - 'Z' */
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35,
    100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'a' - 'z' */
|



















|







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
/* 
 * strtoul.c --
 *
 *	Source code for the "strtoul" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The table below is used to convert from ASCII digits to a numerical
 * equivalent. It maps from '0' through 'z' to integers (100 for non-digit
 * characters).
 */

static char cvtIn[] = {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,		/* '0' - '9' */
    100, 100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'A' - 'Z' */
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35,
    100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'a' - 'z' */
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long int
strtoul(
    const char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion.  Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    const char *p;
    unsigned long int result = 0;
    unsigned digit;
    int anyDigits = 0;
    int negative=0;
    int overflow=0;

    /*
     * Skip any leading blanks.
     */







|











|
|
|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long int
strtoul(
    CONST char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion.  Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    register CONST char *p;
    register unsigned long int result = 0;
    register unsigned digit;
    int anyDigits = 0;
    int negative=0;
    int overflow=0;

    /*
     * Skip any leading blanks.
     */
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
        }
    }

    /*
     * If no base was provided, pick one from the leading characters of the
     * string.
     */

    if (base == 0) {
	if (*p == '0') {
	    p += 1;
	    if ((*p == 'x') || (*p == 'X')) {
		p += 1;
		base = 16;
	    } else {







|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
        }
    }

    /*
     * If no base was provided, pick one from the leading characters of the
     * string.
     */
    
    if (base == 0) {
	if (*p == '0') {
	    p += 1;
	    if ((*p == 'x') || (*p == 'X')) {
		p += 1;
		base = 16;
	    } else {
202
203
204
205
206
207
208
209
210
211
212
213
214
	/* unsafe, but required by the strtoul prototype */
	*endPtr = (char *) p;
    }

    if (overflow) {
	errno = ERANGE;
	return ULONG_MAX;
    }
    if (negative) {
	return -result;
    }
    return result;
}







|





202
203
204
205
206
207
208
209
210
211
212
213
214
	/* unsafe, but required by the strtoul prototype */
	*endPtr = (char *) p;
    }

    if (overflow) {
	errno = ERANGE;
	return ULONG_MAX;
    } 
    if (negative) {
	return -result;
    }
    return result;
}

Changes to compat/unistd.h.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#include <sys/types.h>

#ifndef NULL
#define NULL    0
#endif

/*
 * Strict POSIX stuff goes here. Extensions go down below, in the ifndef
 * _POSIX_SOURCE section.
 */

extern void		_exit(int status);
extern int		access(const char *path, int mode);
extern int		chdir(const char *path);







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#include <sys/types.h>

#ifndef NULL
#define NULL    0
#endif

/* 
 * Strict POSIX stuff goes here. Extensions go down below, in the ifndef
 * _POSIX_SOURCE section.
 */

extern void		_exit(int status);
extern int		access(const char *path, int mode);
extern int		chdir(const char *path);

Changes to compat/waitpid.c.

1
2
3
4
5
6
7
8
/*
 * waitpid.c --
 *
 *	This procedure emulates the POSIX waitpid kernel call on BSD systems
 *	that don't have waitpid but do have wait3. This code is based on a
 *	prototype version written by Mark Diekhans and Karl Lehenbauer.
 *
 * Copyright (c) 1993 The Regents of the University of California.
|







1
2
3
4
5
6
7
8
/* 
 * waitpid.c --
 *
 *	This procedure emulates the POSIX waitpid kernel call on BSD systems
 *	that don't have waitpid but do have wait3. This code is based on a
 *	prototype version written by Mark Diekhans and Karl Lehenbauer.
 *
 * Copyright (c) 1993 The Regents of the University of California.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    pid_t pid,			/* The pid to wait on. Must be -1 or greater
				 * than zero. */
    int *statusPtr,		/* Where to store wait status for the
				 * process. */
    int options)		/* OR'ed combination of WNOHANG and
				 * WUNTRACED. */
{
    WaitInfo *waitPtr, *prevPtr;
    pid_t result;
    WAIT_STATUS_TYPE status;

    if ((pid < -1) || (pid == 0)) {
	errno = EINVAL;
	return -1;
    }







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    pid_t pid,			/* The pid to wait on. Must be -1 or greater
				 * than zero. */
    int *statusPtr,		/* Where to store wait status for the
				 * process. */
    int options)		/* OR'ed combination of WNOHANG and
				 * WUNTRACED. */
{
    register WaitInfo *waitPtr, *prevPtr;
    pid_t result;
    WAIT_STATUS_TYPE status;

    if ((pid < -1) || (pid == 0)) {
	errno = EINVAL;
	return -1;
    }

Changes to doc/Alloc.3.

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
'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc, Tcl_GetMemoryInfo, ckalloc, ckfree, ckrealloc, attemptckalloc, attemptckrealloc \- allocate or free heap memory
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_Alloc\fR(\fIsize\fR)
.sp
void
\fBTcl_Free\fR(\fIptr\fR)
.sp
char *
\fBTcl_Realloc\fR(\fIptr, size\fR)
.sp
char *
\fBTcl_AttemptAlloc\fR(\fIsize\fR)
.sp
char *
\fBTcl_AttemptRealloc\fR(\fIptr, size\fR)
.sp
void
\fBTcl_GetMemoryInfo\fR(\fIdsPtr\fR)
.sp
char *
\fBckalloc\fR(\fIsize\fR)
.sp
void
\fBckfree\fR(\fIptr\fR)
.sp
char *
\fBckrealloc\fR(\fIptr, size\fR)
.sp
char *
\fBattemptckalloc\fR(\fIsize\fR)
.sp
char *
\fBattemptckrealloc\fR(\fIptr, size\fR)
.SH ARGUMENTS
.AS char *size
.AP "unsigned int" size in
Size in bytes of the memory block to allocate.
.AP char *ptr in
Pointer to memory block to free or realloc.
.AP Tcl_DString *dsPtr in
Initialized DString pointer.
.BE

.SH DESCRIPTION
.PP
These procedures provide a platform and compiler independent interface
for memory allocation.  Programs that need to transfer ownership of
memory blocks between Tcl and other modules should use these routines





|




|



















<
<
<




















<
<







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
'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
.TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc, ckalloc, ckfree, ckrealloc, attemptckalloc, attemptckrealloc \- allocate or free heap memory
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_Alloc\fR(\fIsize\fR)
.sp
void
\fBTcl_Free\fR(\fIptr\fR)
.sp
char *
\fBTcl_Realloc\fR(\fIptr, size\fR)
.sp
char *
\fBTcl_AttemptAlloc\fR(\fIsize\fR)
.sp
char *
\fBTcl_AttemptRealloc\fR(\fIptr, size\fR)
.sp



char *
\fBckalloc\fR(\fIsize\fR)
.sp
void
\fBckfree\fR(\fIptr\fR)
.sp
char *
\fBckrealloc\fR(\fIptr, size\fR)
.sp
char *
\fBattemptckalloc\fR(\fIsize\fR)
.sp
char *
\fBattemptckrealloc\fR(\fIptr, size\fR)
.SH ARGUMENTS
.AS char *size
.AP "unsigned int" size in
Size in bytes of the memory block to allocate.
.AP char *ptr in
Pointer to memory block to free or realloc.


.BE

.SH DESCRIPTION
.PP
These procedures provide a platform and compiler independent interface
for memory allocation.  Programs that need to transfer ownership of
memory blocks between Tcl and other modules should use these routines
89
90
91
92
93
94
95
96
97
98
99
100
101
as macros.  Normally, they are synonyms for the corresponding
procedures documented on this page.  When Tcl and all modules
calling Tcl are compiled with \fBTCL_MEM_DEBUG\fR defined, however,
these macros are redefined to be special debugging versions
of these procedures.  To support Tcl's memory debugging within a
module, use the macros rather than direct calls to \fBTcl_Alloc\fR, etc.

\fBTcl_GetMemoryInfo\fR appends a list-of-lists of memory stats to the
provided DString. This function cannot be used in stub-enabled extensions,
and it is only available if Tcl is compiled with the threaded memory allocator.

.SH KEYWORDS
alloc, allocation, free, malloc, memory, realloc, TCL_MEM_DEBUG







<
<
<
<


84
85
86
87
88
89
90




91
92
as macros.  Normally, they are synonyms for the corresponding
procedures documented on this page.  When Tcl and all modules
calling Tcl are compiled with \fBTCL_MEM_DEBUG\fR defined, however,
these macros are redefined to be special debugging versions
of these procedures.  To support Tcl's memory debugging within a
module, use the macros rather than direct calls to \fBTcl_Alloc\fR, etc.





.SH KEYWORDS
alloc, allocation, free, malloc, memory, realloc, TCL_MEM_DEBUG

Changes to doc/ListObj.3.

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
the two procedures return \fBTCL_OK\fR after appending the objects.
.PP
\fBTcl_NewListObj\fR and \fBTcl_SetListObj\fR
create a new object or modify an existing object to hold 
the \fIobjc\fR elements of the array referenced by \fIobjv\fR
where each element is a pointer to a Tcl object.
If \fIobjc\fR is less than or equal to zero,
they return an empty object. If \fIobjv\fR is NULL, the resulting list
contains 0 elements, with reserved space in an internal representation
for \fIobjc\fR more elements (to avoid its reallocation later).
The new object's string representation is left invalid.
The two procedures increment the reference counts
of the elements in \fIobjc\fR since the list object now refers to them.
The new list object returned by \fBTcl_NewListObj\fR
has reference count zero.
.PP
\fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of







|
<
<







134
135
136
137
138
139
140
141


142
143
144
145
146
147
148
the two procedures return \fBTCL_OK\fR after appending the objects.
.PP
\fBTcl_NewListObj\fR and \fBTcl_SetListObj\fR
create a new object or modify an existing object to hold 
the \fIobjc\fR elements of the array referenced by \fIobjv\fR
where each element is a pointer to a Tcl object.
If \fIobjc\fR is less than or equal to zero,
they return an empty object.


The new object's string representation is left invalid.
The two procedures increment the reference counts
of the elements in \fIobjc\fR since the list object now refers to them.
The new list object returned by \fBTcl_NewListObj\fR
has reference count zero.
.PP
\fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of

Changes to doc/ParseCmd.3.

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
.VE 8.5
.TP
\fBTCL_TOKEN_TEXT\fR
The token describes a range of literal text that is part of a word.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_BS\fR
The token describes a backslash sequence such as \fB\en\fR or \fB\e0xA3\fR.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_COMMAND\fR
The token describes a command whose result must be substituted into
the word.  The token includes the square brackets that surround the
command.  The \fInumComponents\fR field is always 0 (the nested command
is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to







|







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
.VE 8.5
.TP
\fBTCL_TOKEN_TEXT\fR
The token describes a range of literal text that is part of a word.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_BS\fR
The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_COMMAND\fR
The token describes a command whose result must be substituted into
the word.  The token includes the square brackets that surround the
command.  The \fInumComponents\fR field is always 0 (the nested command
is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to

Changes to doc/Tcl.n.

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
\e\fBa\fR
Audible alert (bell) (0x7).
.TP 7
\e\fBb\fR
Backspace (0x8).
.TP 7
\e\fBf\fR
Form feed (0xC).
.TP 7
\e\fBn\fR
Newline (0xA).
.TP 7
\e\fBr\fR
Carriage-return (0xD).
.TP 7
\e\fBt\fR
Tab (0x9).
.TP 7
\e\fBv\fR
Vertical tab (0xB).
.TP 7
\e\fB<newline>\fIwhiteSpace\fR
.
A single space character replaces the backslash, newline, and all spaces
and tabs after the newline.  This backslash sequence is unique in that it
is replaced in a separate pre-pass before the command is actually parsed.
This means that it will be replaced even when it occurs between braces,







|


|


|





|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
\e\fBa\fR
Audible alert (bell) (0x7).
.TP 7
\e\fBb\fR
Backspace (0x8).
.TP 7
\e\fBf\fR
Form feed (0xc).
.TP 7
\e\fBn\fR
Newline (0xa).
.TP 7
\e\fBr\fR
Carriage-return (0xd).
.TP 7
\e\fBt\fR
Tab (0x9).
.TP 7
\e\fBv\fR
Vertical tab (0xb).
.TP 7
\e\fB<newline>\fIwhiteSpace\fR
.
A single space character replaces the backslash, newline, and all spaces
and tabs after the newline.  This backslash sequence is unique in that it
is replaced in a separate pre-pass before the command is actually parsed.
This means that it will be replaced even when it occurs between braces,

Changes to doc/ToUpper.3.

77
78
79
80
81
82
83
84
85
86
87
88
\fBTcl_UtfToTitle\fR is the same as \fBTcl_UtfToUpper\fR except it
turns the first character in the string into its title-case equivalent
and all following characters into their lower-case equivalents.

.SH BUGS
.PP
At this time, the case conversions are only defined for the ISO8859-1
characters.  Unicode characters above 0x00FF are not modified by these
routines.

.SH KEYWORDS
utf, unicode, toupper, tolower, totitle, case







|




77
78
79
80
81
82
83
84
85
86
87
88
\fBTcl_UtfToTitle\fR is the same as \fBTcl_UtfToUpper\fR except it
turns the first character in the string into its title-case equivalent
and all following characters into their lower-case equivalents.

.SH BUGS
.PP
At this time, the case conversions are only defined for the ISO8859-1
characters.  Unicode characters above 0x00ff are not modified by these
routines.

.SH KEYWORDS
utf, unicode, toupper, tolower, totitle, case

Changes to doc/TraceVar.3.

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
The return value from \fIproc\fR is only used during read and
write tracing.
During unset traces, the return value is ignored and all relevant
trace procedures will always be invoked.
.SH "RESTRICTIONS"
.PP
A trace procedure can be called at any time, even when there
are partially formed results stored in the interpreter.  If
the trace procedure does anything that could damage this result (such
as calling \fBTcl_Eval\fR) then it must use the \fBTcl_SaveInterpState\fR
and related routines to save and restore the original state of
the interpreter before it returns.
.SH "UNDEFINED VARIABLES"
.PP
It is legal to set a trace on an undefined variable.
The variable will still appear to be undefined until the
first time its value is set.
If an undefined variable is traced and then unset, the unset will fail
with an error







|

|
|
|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
The return value from \fIproc\fR is only used during read and
write tracing.
During unset traces, the return value is ignored and all relevant
trace procedures will always be invoked.
.SH "RESTRICTIONS"
.PP
A trace procedure can be called at any time, even when there
is a partially formed result in the interpreter's result area.  If
the trace procedure does anything that could damage this result (such
as calling \fBTcl_Eval\fR) then it must save the original values of
the interpreter's \fBresult\fR and \fBfreeProc\fR fields and restore
them before it returns.
.SH "UNDEFINED VARIABLES"
.PP
It is legal to set a trace on an undefined variable.
The variable will still appear to be undefined until the
first time its value is set.
If an undefined variable is traced and then unset, the unset will fail
with an error

Changes to doc/Utf.3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Utf 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
typedef ... \fBTcl_UniChar\fR;
.sp
int
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
int
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.sp





|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
.TH Utf 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
typedef ... Tcl_UniChar;
.sp
int
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
int
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.sp
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
.sp
int
\fBTcl_UtfNcasecmp\fR(\fIcs, ct, numChars\fR)
.sp
int
\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR)
.sp
int
\fBTcl_NumUtfChars\fR(\fIsrc, length\fR)
.sp
const char *
\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR)







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
.sp
int
\fBTcl_UtfNcasecmp\fR(\fIcs, ct, numChars\fR)
.sp
int
\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR)
.sp
int 
\fBTcl_NumUtfChars\fR(\fIsrc, length\fR)
.sp
const char *
\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR)
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
.AP "unsigned long" numChars in
The number of characters to compare.
.AP "const char" *start in
Pointer to the beginning of a UTF-8 string.
.AP int index in
The index of a character (not byte) in the UTF-8 string.
.AP int *readPtr out
If non-NULL, filled with the number of bytes in the backslash sequence,
including the backslash character.
.AP char *dst out
Buffer in which the bytes represented by the backslash sequence are stored.
At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int nocase in
Specifies whether the match should be done case-sensitive (0) or
case-insensitive (1).







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
.AP "unsigned long" numChars in
The number of characters to compare.
.AP "const char" *start in
Pointer to the beginning of a UTF-8 string.
.AP int index in
The index of a character (not byte) in the UTF-8 string.
.AP int *readPtr out
If non-NULL, filled with the number of bytes in the backslash sequence, 
including the backslash character.
.AP char *dst out
Buffer in which the bytes represented by the backslash sequence are stored.
At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int nocase in
Specifies whether the match should be done case-sensitive (0) or
case-insensitive (1).
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
\fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR
and stores it as a Tcl_UniChar in \fI*chPtr\fR.  The return value is the
number of bytes read from \fIsrc\fR.  The caller must ensure that the
source buffer is long enough such that this routine does not run off the
end and dereference non-existent or random memory; if the source buffer
is known to be null-terminated, this will not happen.  If the input is
not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first
byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x80 and
0xFF and return 1.
.PP
\fBTcl_UniCharToUtfDString\fR converts the given Unicode string
to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR.
You must specify \fIuniLength\fR, the length of the given Unicode string.
The return value is a pointer to the UTF-8 representation of the
Unicode string.  Storage for the return value is appended to the
end of the \fBTcl_DString\fR.







|
|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
\fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR
and stores it as a Tcl_UniChar in \fI*chPtr\fR.  The return value is the
number of bytes read from \fIsrc\fR.  The caller must ensure that the
source buffer is long enough such that this routine does not run off the
end and dereference non-existent or random memory; if the source buffer
is known to be null-terminated, this will not happen.  If the input is
not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first
byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and
0x00ff and return 1.  
.PP
\fBTcl_UniCharToUtfDString\fR converts the given Unicode string
to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR.
You must specify \fIuniLength\fR, the length of the given Unicode string.
The return value is a pointer to the UTF-8 representation of the
Unicode string.  Storage for the return value is appended to the
end of the \fBTcl_DString\fR.
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
\fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8
strings.  It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore
differences in case when comparing upper, lower or title case
characters.
.PP
\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR
of \fIlength\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR/\fBTcl_UtfNext\fR, or 0 otherwise.  This function
does not guarantee that the UTF-8 string is properly formed.  This routine
is used by procedures that are operating on a byte at a time and need to
know if a full Tcl_UniChar has been seen.
.PP
\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings.  It
returns the number of Tcl_UniChars that are represented by the UTF-8 string
\fIsrc\fR.  The length of the source string is \fIlength\fR bytes.  If the
length is negative, all bytes up to the first null byte are used.
.PP
\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings.  It
returns a pointer to the first occurrence of the Tcl_UniChar \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.
.PP
\fBTcl_UtfFindLast\fR corresponds to \fBstrrchr\fR for UTF-8 strings.  It
returns a pointer to the last occurrence of the Tcl_UniChar \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.
.PP
Given \fIsrc\fR, a pointer to some location in a UTF-8 string,
\fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the
string.  The caller must not ask for the next character after the last
character in the string if the string is not terminated by a null
character. \fBTcl_UtfCharComplete\fR can be used in that case to
make sure enough bytes are available before calling \fBTcl_UtfNext\fR.
.PP
\fBTcl_UtfPrev\fR is used to step backward through but not beyond the
UTF-8 string that begins at \fIstart\fR.  If the UTF-8 string is made
up entirely of complete and well-formed characters, and \fIsrc\fR points
to the lead byte of one of those characters (or to the location one byte
past the end of the string), then repeated calls of \fBTcl_UtfPrev\fR will
return pointers to the lead bytes of each character in the string, one
character at a time, terminating when it returns \fIstart\fR.
.PP
When the conditions of completeness and well-formedness may not be satisfied,
a more precise description of the function of \fBTcl_UtfPrev\fR is necessary.
It always returns a pointer greater than or equal to \fIstart\fR; that is,
always a pointer to a location in the string. It always returns a pointer to
a byte that begins a character when scanning for characters beginning
from \fIstart\fR. When \fIsrc\fR is greater than \fIstart\fR, it
always returns a pointer less than \fIsrc\fR and greater than or
equal to (\fIsrc\fR - \fBTCL_UTF_MAX\fR).  The character that begins
at the returned pointer is the first one that either includes the
byte \fIsrc[-1]\fR, or might include it if the right trail bytes are
present at \fIsrc\fR and greater. \fBTcl_UtfPrev\fR never reads the
byte \fIsrc[0]\fR nor the byte \fIstart[-1]\fR nor the byte
\fIsrc[-\fBTCL_UTF_MAX\fI-1]\fR.
.PP
\fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the
Pascal Ord() function.  It returns the Tcl_UniChar represented at the
specified character (not byte) \fIindex\fR in the UTF-8 string
\fIsrc\fR.  The source string must contain at least \fIindex\fR
characters.  Behavior is undefined if a negative \fIindex\fR is given.
.PP
\fBTcl_UtfAtIndex\fR returns a pointer to the specified character (not
byte) \fIindex\fR in the UTF-8 string \fIsrc\fR.  The source string must
contain at least \fIindex\fR characters.  This is equivalent to calling
\fBTcl_UtfToUniChar\fR \fIindex\fR times.  If a negative \fIindex\fR is given,
the return pointer points to the first character in the source string.
.PP
\fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl
commands.  It parses a backslash sequence and stores the properly formed
UTF-8 character represented by the backslash sequence in the output
buffer \fIdst\fR.  At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
\fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number







|
|
|
|









|




|





|
<

<
|
<
<
|
<
<
<
<
<
<
|
|
|
|
<
<
<
<
|
<









|
|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225

226


227






228
229
230
231




232

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
\fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8
strings.  It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore
differences in case when comparing upper, lower or title case
characters.
.PP
\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR
of \fIlength\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR, or 0 otherwise.  This function does not guarantee
that the UTF-8 string is properly formed.  This routine is used by
procedures that are operating on a byte at a time and need to know if a
full Tcl_UniChar has been seen.
.PP
\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings.  It
returns the number of Tcl_UniChars that are represented by the UTF-8 string
\fIsrc\fR.  The length of the source string is \fIlength\fR bytes.  If the
length is negative, all bytes up to the first null byte are used.
.PP
\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings.  It
returns a pointer to the first occurrence of the Tcl_UniChar \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.  
.PP
\fBTcl_UtfFindLast\fR corresponds to \fBstrrchr\fR for UTF-8 strings.  It
returns a pointer to the last occurrence of the Tcl_UniChar \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.  
.PP
Given \fIsrc\fR, a pointer to some location in a UTF-8 string,
\fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the
string.  The caller must not ask for the next character after the last
character in the string if the string is not terminated by a null
character.

.PP

Given \fIsrc\fR, a pointer to some location in a UTF-8 string (or to a


null byte immediately following such a string), \fBTcl_UtfPrev\fR






returns a pointer to the closest preceding byte that starts a UTF-8
character.
This function will not back up to a position before \fIstart\fR,
the start of the UTF-8 string.  If \fIsrc\fR was already at \fIstart\fR, the




return value will be \fIstart\fR.

.PP
\fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the
Pascal Ord() function.  It returns the Tcl_UniChar represented at the
specified character (not byte) \fIindex\fR in the UTF-8 string
\fIsrc\fR.  The source string must contain at least \fIindex\fR
characters.  Behavior is undefined if a negative \fIindex\fR is given.
.PP
\fBTcl_UtfAtIndex\fR returns a pointer to the specified character (not
byte) \fIindex\fR in the UTF-8 string \fIsrc\fR.  The source string must
contain at least \fIindex\fR characters.  This is equivalent to calling 
\fBTcl_UtfNext\fR \fIindex\fR times.  If a negative \fIindex\fR is given,
the return pointer points to the first character in the source string.
.PP
\fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl
commands.  It parses a backslash sequence and stores the properly formed
UTF-8 character represented by the backslash sequence in the output
buffer \fIdst\fR.  At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
\fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number

Changes to doc/binary.n.

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
\fBbinary scan\fR \ex07\ex86\ex05 c2c* var1 var2
.CE
will return \fB2\fR with \fB7 -122\fR stored in \fIvar1\fR and \fB5\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 8-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xFF }]
.CE
.RE
.IP \fBs\fR 5
The data is interpreted as \fIcount\fR 16-bit signed integers
represented in little-endian byte order.  The integers are stored in
the corresponding variable as a list.  If \fIcount\fR is \fB*\fR, then
all of the remaining bytes in \fIstring\fR will be scanned.  If
\fIcount\fR is omitted, then one 16-bit integer will be scanned.  For
example,
.RS
.CS
\fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2
.CE
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 16-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xFFFF }]
.CE
.RE
.IP \fBS\fR 5
This form is the same as \fBs\fR except that the data is interpreted
as \fIcount\fR 16-bit signed integers represented in big-endian byte
order.  For example,
.RS







|


















|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
\fBbinary scan\fR \ex07\ex86\ex05 c2c* var1 var2
.CE
will return \fB2\fR with \fB7 -122\fR stored in \fIvar1\fR and \fB5\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 8-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xff }]
.CE
.RE
.IP \fBs\fR 5
The data is interpreted as \fIcount\fR 16-bit signed integers
represented in little-endian byte order.  The integers are stored in
the corresponding variable as a list.  If \fIcount\fR is \fB*\fR, then
all of the remaining bytes in \fIstring\fR will be scanned.  If
\fIcount\fR is omitted, then one 16-bit integer will be scanned.  For
example,
.RS
.CS
\fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2
.CE
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 16-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xffff }]
.CE
.RE
.IP \fBS\fR 5
This form is the same as \fBs\fR except that the data is interpreted
as \fIcount\fR 16-bit signed integers represented in big-endian byte
order.  For example,
.RS
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
\fBbinary scan\fR $str i2i* var1 var2
.CE
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 32-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xFFFFFFFF }]
.CE
.RE
.IP \fBI\fR 5
This form is the same as \fBI\fR except that the data is interpreted
as \fIcount\fR 32-bit signed integers represented in big-endian byte
order.  For example,
.RS







|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
\fBbinary scan\fR $str i2i* var1 var2
.CE
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed, but
they can be converted to unsigned 32-bit quantities using an expression
like:
.CS
set num [expr { $num & 0xffffffff }]
.CE
.RE
.IP \fBI\fR 5
This form is the same as \fBI\fR except that the data is interpreted
as \fIcount\fR 32-bit signed integers represented in big-endian byte
order.  For example,
.RS

Changes to doc/clock.n.

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
time zone when converting local times.  This caveat does not apply to
UTC times.)
.SH "FORMAT GROUPS"
The following format groups are recognized by the \fBclock scan\fR and
\fBclock format\fR commands.
.TP
\fB%a\fR
On output, produces an abbreviation (\fIe.g.,\fR \fBMon\fR) for the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%A\fR
On output, produces the full name (\fIe.g.,\fR \fBMonday\fR) of the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%b\fR
On output, produces an abbreviation (\fIe.g.,\fR \fBJan\fR) for the name
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%B\fR
On output, produces the full name (\fIe.g.,\fR \fBJanuary\fR)
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%c\fR
On output, produces a localized representation of date and time of day;
the localized representation is expected to use the Gregorian calendar.
On input, matches whatever \fB%c\fR produces.
.TP
\fB%C\fR
On output, produces the number of the century in Indo-Arabic numerals.
On input, matches one or two digits, possibly with leading whitespace,
that are expected to be the number of the century.
.TP
\fB%d\fR
On output, produces the number of the day of the month, as two decimal
digits.  On input, matches one or two digits, possibly with leading
whitespace, that are expected to be the number of the day of the month.







|





|





|





|





|




|







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
time zone when converting local times.  This caveat does not apply to
UTC times.)
.SH "FORMAT GROUPS"
The following format groups are recognized by the \fBclock scan\fR and
\fBclock format\fR commands.
.TP
\fB%a\fR
On output, receives an abbreviation (\fIe.g.,\fR \fBMon\fR) for the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%A\fR
On output, receives the full name (\fIe.g.,\fR \fBMonday\fR) of the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%b\fR
On output, receives an abbreviation (\fIe.g.,\fR \fBJan\fR) for the name
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%B\fR
On output, receives the full name (\fIe.g.,\fR \fBJanuary\fR)
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%c\fR
On output, receives a localized representation of date and time of day;
the localized representation is expected to use the Gregorian calendar.
On input, matches whatever \fB%c\fR produces.
.TP
\fB%C\fR
On output, receives the number of the century in Indo-Arabic numerals.
On input, matches one or two digits, possibly with leading whitespace,
that are expected to be the number of the century.
.TP
\fB%d\fR
On output, produces the number of the day of the month, as two decimal
digits.  On input, matches one or two digits, possibly with leading
whitespace, that are expected to be the number of the day of the month.

Changes to doc/exec.n.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.SH DESCRIPTION
.PP
This command treats its arguments as the specification
of one or more subprocesses to execute.
The arguments take the form of a standard shell pipeline
where each \fIarg\fR becomes one word of a command, and
each distinct command becomes a subprocess.
The result of the command is the standard output of the final subprocess in
the pipeline, interpreted using the system \fBencoding\fR; to use any other
encoding (especially including binary data), the pipeline must be
\fBopen\fRed, configured and read explicitly.
.PP
If the initial arguments to \fBexec\fR start with \fB\-\fR then
they are treated as command-line switches and are not part
of the pipeline specification.  The following switches are
currently supported:
.TP 13
\fB\-ignorestderr\fR







<
<
<
<







19
20
21
22
23
24
25




26
27
28
29
30
31
32
.SH DESCRIPTION
.PP
This command treats its arguments as the specification
of one or more subprocesses to execute.
The arguments take the form of a standard shell pipeline
where each \fIarg\fR becomes one word of a command, and
each distinct command becomes a subprocess.




.PP
If the initial arguments to \fBexec\fR start with \fB\-\fR then
they are treated as command-line switches and are not part
of the pipeline specification.  The following switches are
currently supported:
.TP 13
\fB\-ignorestderr\fR
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
notation, does not work.  When reading from a socket, a 16-bit DOS
application will hang and a 32-bit application will return immediately with
end-of-file.  When either type of application writes to a socket, the
information is instead sent to the console, if one is present, or is
discarded.
.RS
.PP
Note that the current escape resp. quoting of arguments for windows works only
with executables using CommandLineToArgv, CRT-library or similar, as well as
with the windows batch files (excepting the newline, see below).
Although it is the common escape algorithm, but, in fact, the way how the
executable parses the command-line (resp. splits it into single arguments)
is decisive.
.PP
Unfortunately, there is currently no way to supply newline character within 
an argument to the batch files (\fB.cmd\fR or \fB.bat\fR) or to the command 
processor (\fBcmd.exe /c\fR), because this causes truncation of command-line
(also the argument chain) on the first newline character. 
But it works properly with an executable (using CommandLineToArgv, etc).
.PP
The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
error will be discarded.  
.PP
Either forward or backward slashes are accepted as path separators for
arguments to Tcl commands.  When executing an application, the path name







<
<
<
<
<
<
<
<
<
<
<
<
<







203
204
205
206
207
208
209













210
211
212
213
214
215
216
notation, does not work.  When reading from a socket, a 16-bit DOS
application will hang and a 32-bit application will return immediately with
end-of-file.  When either type of application writes to a socket, the
information is instead sent to the console, if one is present, or is
discarded.
.RS
.PP













The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
error will be discarded.  
.PP
Either forward or backward slashes are accepted as path separators for
arguments to Tcl commands.  When executing an application, the path name
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
.TP
\fBUnix\fR\0\0\0\0\0\0\0
The \fBexec\fR command is fully functional and works as described.
.SH "UNIX EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Unix.
.PP
To execute a simple program and get its result:
.PP
.CS
\fBexec\fR uname -a
.CE
.PP
To execute a program that can return a non-zero result, you should
wrap the call to \fBexec\fR in \fBcatch\fR and check the contents
of the \fB\-errorcode\fR return option if you have an error:
.PP
.CS
set status 0
if {[catch {\fBexec\fR grep foo bar.txt} results options]} {
   set details [dict get $options -errorcode]
   if {[lindex $details 0] eq "CHILDSTATUS"} {
      set status [lindex $details 2]
   } else {
      # Some kind of unexpected failure
   }
}
.CE
.PP
When translating a command from a Unix shell invocation, care should
be taken over the fact that single quote characters have no special
significance to Tcl.  Thus:
.PP
.CS
awk '{sum += $1} END {print sum}' numbers.list
.CE
.PP
would be translated into something like:
.PP
.CS
\fBexec\fR awk {{sum += $1} END {print sum}} numbers.list
.CE
.PP
If you are converting invocations involving shell globbing, you should
remember that Tcl does not handle globbing or expand things into
multiple arguments by default.  Instead you should write things like
this:
.PP
.CS
\fBexec\fR ls -l {*}[glob *.tcl]
.CE
.SH "WINDOWS EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Windows.
.PP
To start an instance of \fInotepad\fR editing a file without waiting
for the user to finish editing the file:
.PP
.CS
\fBexec\fR notepad myfile.txt &
.CE
.PP
To print a text file using \fInotepad\fR:
.PP
.CS
\fBexec\fR notepad /p myfile.txt
.CE
.PP
To print a text file in a directory other than the current one using
\fInotepad\fR, you need to use \fBfile nativename\fR to convert the name into
a form that will be understood by the other program:
.PP
.CS
\fBexec\fR notepad /p [file nativename some/dir/myfile.txt]
.CE
.PP
If a program calls other programs, such as is common with compilers,
then you may need to resort to batch files to hide the console windows
that sometimes pop up:
.PP
.CS
\fBexec\fR cmp.bat somefile.c -o somefile
.CE
.PP
With the file \fIcmp.bat\fR looking something like:
.PP
.CS
@gcc %*
.CE
.PP
or like another variant using single parameters:
.PP
.CS
@gcc %1 %2 %3 %4 %5 %6 %7 %8 %9
.CE
.PP
Sometimes you need to be careful, as different programs may have the
same name and be in the path. It can then happen that typing a command
at the DOS prompt finds \fIa different program\fR than the same
command run via \fBexec\fR. This is because of the (documented)
differences in behaviour between \fBexec\fR and DOS batch files.
.PP
When in doubt, use the command \fBauto_execok\fR: it will return the
complete path to the program as seen by the \fBexec\fR command.  This
applies especially when you want to run
.QW internal
commands like
\fIdir\fR from a Tcl script (if you just want to list filenames, use
the \fBglob\fR command.)  To do that, use this:
.PP
.CS
\fBexec\fR {*}[auto_execok dir] *.tcl
.CE
.SH "SEE ALSO"
error(n), open(n)
.SH KEYWORDS
execute, pipeline, redirection, subprocess







<







<















<



<

<








<








<





<



<
<
<
<
<
<
<
<




<



<

<
<
<
<
<
<
<

















<







352
353
354
355
356
357
358

359
360
361
362
363
364
365

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382
383

384

385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400

401
402
403
404
405

406
407
408








409
410
411
412

413
414
415

416







417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
.TP
\fBUnix\fR\0\0\0\0\0\0\0
The \fBexec\fR command is fully functional and works as described.
.SH "UNIX EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Unix.
.PP
To execute a simple program and get its result:

.CS
\fBexec\fR uname -a
.CE
.PP
To execute a program that can return a non-zero result, you should
wrap the call to \fBexec\fR in \fBcatch\fR and check the contents
of the \fB\-errorcode\fR return option if you have an error:

.CS
set status 0
if {[catch {\fBexec\fR grep foo bar.txt} results options]} {
   set details [dict get $options -errorcode]
   if {[lindex $details 0] eq "CHILDSTATUS"} {
      set status [lindex $details 2]
   } else {
      # Some kind of unexpected failure
   }
}
.CE
.PP
When translating a command from a Unix shell invocation, care should
be taken over the fact that single quote characters have no special
significance to Tcl.  Thus:

.CS
awk '{sum += $1} END {print sum}' numbers.list
.CE

would be translated into something like:

.CS
\fBexec\fR awk {{sum += $1} END {print sum}} numbers.list
.CE
.PP
If you are converting invocations involving shell globbing, you should
remember that Tcl does not handle globbing or expand things into
multiple arguments by default.  Instead you should write things like
this:

.CS
\fBexec\fR ls -l {*}[glob *.tcl]
.CE
.SH "WINDOWS EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Windows.
.PP
To start an instance of \fInotepad\fR editing a file without waiting
for the user to finish editing the file:

.CS
\fBexec\fR notepad myfile.txt &
.CE
.PP
To print a text file using \fInotepad\fR:

.CS
\fBexec\fR notepad /p myfile.txt
.CE








.PP
If a program calls other programs, such as is common with compilers,
then you may need to resort to batch files to hide the console windows
that sometimes pop up:

.CS
\fBexec\fR cmp.bat somefile.c -o somefile
.CE

With the file \fIcmp.bat\fR looking something like:







.CS
@gcc %1 %2 %3 %4 %5 %6 %7 %8 %9
.CE
.PP
Sometimes you need to be careful, as different programs may have the
same name and be in the path. It can then happen that typing a command
at the DOS prompt finds \fIa different program\fR than the same
command run via \fBexec\fR. This is because of the (documented)
differences in behaviour between \fBexec\fR and DOS batch files.
.PP
When in doubt, use the command \fBauto_execok\fR: it will return the
complete path to the program as seen by the \fBexec\fR command.  This
applies especially when you want to run
.QW internal
commands like
\fIdir\fR from a Tcl script (if you just want to list filenames, use
the \fBglob\fR command.)  To do that, use this:

.CS
\fBexec\fR {*}[auto_execok dir] *.tcl
.CE
.SH "SEE ALSO"
error(n), open(n)
.SH KEYWORDS
execute, pipeline, redirection, subprocess

Changes to doc/expr.n.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
The operators permitted in Tcl expressions include a subset of
the operators permitted in C expressions.  For those operators
common to both Tcl and C, Tcl applies the same meaning and precedence
as the corresponding C operators.
Expressions almost always yield numeric results
(integer or floating-point values).
For example, the expression
.PP
.CS
\fBexpr 8.2 + 6\fR
.CE
.PP
evaluates to 14.2.
Tcl expressions differ from C expressions in the way that
operands are specified.  Also, Tcl expressions support
non-numeric operands and string comparisons, as well as some
additional operators not found in C.
.SS OPERANDS
.PP







<



<







22
23
24
25
26
27
28

29
30
31

32
33
34
35
36
37
38
The operators permitted in Tcl expressions include a subset of
the operators permitted in C expressions.  For those operators
common to both Tcl and C, Tcl applies the same meaning and precedence
as the corresponding C operators.
Expressions almost always yield numeric results
(integer or floating-point values).
For example, the expression

.CS
\fBexpr 8.2 + 6\fR
.CE

evaluates to 14.2.
Tcl expressions differ from C expressions in the way that
operands are specified.  Also, Tcl expressions support
non-numeric operands and string comparisons, as well as some
additional operators not found in C.
.SS OPERANDS
.PP
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
on the contents.
.PP
For some examples of simple expressions, suppose the variable
\fBa\fR has the value 3 and
the variable \fBb\fR has the value 6.
Then the command on the left side of each of the lines below
will produce the value on the right side of the line:
.PP
.CS
.ta 9c
\fBexpr\fR 3.1 + $a	\fI6.1\fR
\fBexpr\fR 2 + "$a.$b"	\fI5.6\fR
\fBexpr\fR 4*[llength "6 2"]	\fI8\fR
\fBexpr\fR {{word one} < "word $a"}	\fI0\fR
.CE
.SS OPERATORS
.PP







<

|







99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
on the contents.
.PP
For some examples of simple expressions, suppose the variable
\fBa\fR has the value 3 and
the variable \fBb\fR has the value 6.
Then the command on the left side of each of the lines below
will produce the value on the right side of the line:

.CS
.ta 6c
\fBexpr\fR 3.1 + $a	\fI6.1\fR
\fBexpr\fR 2 + "$a.$b"	\fI5.6\fR
\fBexpr\fR 4*[llength "6 2"]	\fI8\fR
\fBexpr\fR {{word one} < "word $a"}	\fI0\fR
.CE
.SS OPERATORS
.PP
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
\fB|\fR
Bit-wise OR.  Valid for integer operands only.
.TP 20
\fB&&\fR
Logical AND.  Produces a 1 result if both operands are non-zero,
0 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.
This operator evaluates lazily; it only evaluates its right-hand side if it
must in order to determine its result.
.TP 20
\fB||\fR
Logical OR.  Produces a 0 result if both operands are zero, 1 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.
This operator evaluates lazily; it only evaluates its right-hand side if it
must in order to determine its result.
.TP 20
\fIx \fB? \fIy \fB: \fIz\fR
If-then-else, as in C.  If \fIx\fR
evaluates to non-zero, then the result is the value of \fIy\fR.
Otherwise the result is the value of \fIz\fR.
The \fIx\fR operand must have a boolean or numeric value.
This operator evaluates lazily; it only evaluates one of \fIy\fR or \fIz\fR.
.LP
See the C manual for more details on the results
produced by each operator.
.VS 8.5
The exponentiation operator promotes types like the multiply and
divide operators, and produces a result that is the same as the output
of the \fBpow\fR function (after any type conversions.)
.VE 8.5
All of the binary operators group left-to-right within the same
precedence level.  For example, the command
.PP
.CS
\fBexpr\fR {4*2 < 7}
.CE
.PP
returns 0.
.PP
The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have
.QW "lazy evaluation" ,
just as in C, which means that operands are not evaluated if they are
not needed to determine the outcome.  For example, in the command
.PP
.CS
\fBexpr\fR {$v ? [a] : [b]}
.CE
.PP
only one of
.QW \fB[a]\fR
or
.QW \fB[b]\fR
will actually be evaluated,
depending on the value of \fB$v\fR.  Note, however, that this is
only true if the entire expression is enclosed in braces;  otherwise
the Tcl parser will evaluate both
.QW \fB[a]\fR
and
.QW \fB[b]\fR
before invoking the \fBexpr\fR command.
.SS "MATH FUNCTIONS"
.PP
.VS 8.5
When the expression parser encounters a mathematical function
such as \fBsin($x)\fR, it replaces it with a call to an ordinary
Tcl command in the \fBtcl::mathfunc\fR namespace.  The processing
of an expression such as:
.PP
.CS
\fBexpr\fR {sin($x+$y)}
.CE
.PP
is the same in every way as the processing of:
.PP
.CS
\fBexpr\fR {[tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]]}
.CE
.PP
which in turn is the same as the processing of:
.PP
.CS
tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]
.CE
.PP
The executor will search for \fBtcl::mathfunc::sin\fR using the usual
rules for resolving functions in namespaces. Either
\fB::tcl::mathfunc::sin\fR or \fB[namespace
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
may as well (depending on the current \fBnamespace path\fR setting).







<
<




<
<

|




<










<



<






<

|

<

















|

<

|

<

<

|

<

<

|







185
186
187
188
189
190
191


192
193
194
195


196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211

212
213
214

215
216
217
218
219
220

221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245

246

247
248
249

250

251
252
253
254
255
256
257
258
259
\fB|\fR
Bit-wise OR.  Valid for integer operands only.
.TP 20
\fB&&\fR
Logical AND.  Produces a 1 result if both operands are non-zero,
0 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.


.TP 20
\fB||\fR
Logical OR.  Produces a 0 result if both operands are zero, 1 otherwise.
Valid for boolean and numeric (integers or floating-point) operands only.


.TP 20
\fIx\fB?\fIy\fB:\fIz\fR
If-then-else, as in C.  If \fIx\fR
evaluates to non-zero, then the result is the value of \fIy\fR.
Otherwise the result is the value of \fIz\fR.
The \fIx\fR operand must have a boolean or numeric value.

.LP
See the C manual for more details on the results
produced by each operator.
.VS 8.5
The exponentiation operator promotes types like the multiply and
divide operators, and produces a result that is the same as the output
of the \fBpow\fR function (after any type conversions.)
.VE 8.5
All of the binary operators group left-to-right within the same
precedence level.  For example, the command

.CS
\fBexpr\fR {4*2 < 7}
.CE

returns 0.
.PP
The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have
.QW "lazy evaluation" ,
just as in C, which means that operands are not evaluated if they are
not needed to determine the outcome.  For example, in the command

.CS
\fBexpr {$v ? [a] : [b]}\fR
.CE

only one of
.QW \fB[a]\fR
or
.QW \fB[b]\fR
will actually be evaluated,
depending on the value of \fB$v\fR.  Note, however, that this is
only true if the entire expression is enclosed in braces;  otherwise
the Tcl parser will evaluate both
.QW \fB[a]\fR
and
.QW \fB[b]\fR
before invoking the \fBexpr\fR command.
.SS "MATH FUNCTIONS"
.PP
.VS 8.5
When the expression parser encounters a mathematical function
such as \fBsin($x)\fR, it replaces it with a call to an ordinary
Tcl function in the \fBtcl::mathfunc\fR namespace.  The processing
of an expression such as:

.CS
\fBexpr {sin($x+$y)}\fR
.CE

is the same in every way as the processing of:

.CS
\fBexpr {[tcl::mathfunc::sin [expr {$x+$y}]]}\fR
.CE

which in turn is the same as the processing of:

.CS
\fBtcl::mathfunc::sin [expr {$x+$y}]\fR
.CE
.PP
The executor will search for \fBtcl::mathfunc::sin\fR using the usual
rules for resolving functions in namespaces. Either
\fB::tcl::mathfunc::sin\fR or \fB[namespace
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
may as well (depending on the current \fBnamespace path\fR setting).
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
pretty reliable.
.PP
Conversion among internal representations for integer, floating-point,
and string operands is done automatically as needed.
For arithmetic computations, integers are used until some
floating-point number is introduced, after which floating-point is used.
For example,
.PP
.CS
\fBexpr\fR {5 / 4}
.CE
.PP
returns 1, while
.PP
.CS
\fBexpr\fR {5 / 4.0}
\fBexpr\fR {5 / ( [string length "abcd"] + 0.0 )}
.CE
.PP
both return 1.25.
Floating-point values are always returned with a
.QW \fB.\fR
or an
.QW \fBe\fR
so that they will not look like integer values.  For example,
.PP
.CS
\fBexpr\fR {20.0/5.0}
.CE
.PP
returns \fB4.0\fR, not \fB4\fR.
.SS "STRING OPERATIONS"
.PP
String values may be used as operands of the comparison operators,
although the expression evaluator tries to do comparisons as integer
or floating-point when it can,
i.e., when all arguments to the operator allow numeric interpretations,
except in the case of the \fBeq\fR and \fBne\fR operators.
If one of the operands of a comparison is a string and the other
has a numeric value, a canonical string representation of the numeric
operand value is generated to compare with the string operand.
Canonical string representation for integer values is a decimal string
format.  Canonical string representation for floating-point values
is that produced by the \fB%g\fR format specifier of Tcl's
\fBformat\fR command.  For example, the commands
.PP
.CS
\fBexpr\fR {"0x03" > "2"}
\fBexpr\fR {"0y" > "0x12"}
.CE
.PP
both return 1.  The first comparison is done using integer
comparison, and the second is done using string comparison.
Because of Tcl's tendency to treat values as numbers whenever
possible, it is not generally a good idea to use operators like \fB==\fR
when you really want string comparison and the values of the
operands could be arbitrary;  it is better in these cases to use
the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead.
.SH "PERFORMANCE CONSIDERATIONS"
.PP
Enclose expressions in braces for the best speed and the smallest
storage requirements.
This allows the Tcl bytecode compiler to generate the best code.
.PP
As mentioned above, expressions are substituted twice:
once by the Tcl parser and once by the \fBexpr\fR command.
For example, the commands
.PP
.CS
set a 3
set b {$a + 2}
\fBexpr\fR $b*4
.CE
.PP
return 11, not a multiple of 4.
This is because the Tcl parser will first substitute
.QW "\fB$a + 2\fR"
for the variable \fBb\fR,
then the \fBexpr\fR command will evaluate the expression
.QW "\fB$a + 2*4\fR" .
.PP
Most expressions do not require a second round of substitutions.
Either they are enclosed in braces or, if not,
their variable and command substitutions yield numbers or strings
that do not themselves require substitutions.
However, because a few unbraced expressions 
need two rounds of substitutions,
the bytecode compiler must emit
additional instructions to handle this situation.
The most expensive code is required for
unbraced expressions that contain command substitutions.
These expressions must be implemented by generating new code
each time the expression is executed.
.PP
If it is necessary to include a non-constant expression string within the
wider context of an otherwise-constant expression, the most efficient
technique is to put the varying part inside a recursive \fBexpr\fR, as this at
least allows for the compilation of the outer part, though it does mean that
the varying part must itself be evaluated as a separate expression. Thus, in
this example the result is 20 and the outer expression benefits from fully
cached bytecode compilation.
.PP
.CS
set a 3
set b {$a + 2}
\fBexpr\fR {[\fBexpr\fR $b] * 4}
.CE
.PP
.VS 8.5
When the expression is unbraced to allow the substitution of a function or
operator, consider using the commands documented in the \fBmathfunc\fR(n) or
\fBmathop\fR(n) manual pages directly instead.
.VE 8.5
.SH EXAMPLES
Define a procedure that computes an
.QW interesting
mathematical function:
.PP
.CS
proc tcl::mathfunc::calc {x y} {
    \fBexpr\fR { ($x**2 - $y**2) / exp($x**2 + $y**2) }
}
.CE
.PP
Convert polar coordinates into cartesian coordinates:
.PP
.CS
# convert from ($radius,$angle)
set x [\fBexpr\fR { $radius * cos($angle) }]
set y [\fBexpr\fR { $radius * sin($angle) }]
.CE
.PP
Convert cartesian coordinates into polar coordinates:
.PP
.CS
# convert from ($x,$y)
set radius [\fBexpr\fR { hypot($y, $x) }]
set angle  [\fBexpr\fR { atan2($y, $x) }]
.CE
.PP
Print a message describing the relationship of two string values to
each other:
.PP
.CS
puts "a and b are [\fBexpr\fR {$a eq $b ? {equal} : {different}}]"
.CE
.PP
Set a variable to whether an environment variable is both defined at
all and also set to a true boolean value:
.PP
.CS
set isTrue [\fBexpr\fR {
    [info exists ::env(SOME_ENV_VAR)] &&
    [string is true -strict $::env(SOME_ENV_VAR)]
}]
.CE
.PP
Generate a random integer in the range 0..99 inclusive:
.PP
.CS
set randNum [\fBexpr\fR { int(100 * rand()) }]
.CE
.SH "SEE ALSO"
array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n),
string(n), Tcl(n), while(n)
.SH KEYWORDS







<



<

<




<






<



<















<

|
|

<
















<

|
|
|

<

|
<
|
|
<













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









<







<







<








<






<








<







284
285
286
287
288
289
290

291
292
293

294

295
296
297
298

299
300
301
302
303
304

305
306
307

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

323
324
325
326

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

343
344
345
346
347

348
349

350
351

352
353
354
355
356
357
358
359
360
361
362
363
364















365
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380

381
382
383
384
385
386
387

388
389
390
391
392
393
394
395

396
397
398
399
400
401

402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
pretty reliable.
.PP
Conversion among internal representations for integer, floating-point,
and string operands is done automatically as needed.
For arithmetic computations, integers are used until some
floating-point number is introduced, after which floating-point is used.
For example,

.CS
\fBexpr\fR {5 / 4}
.CE

returns 1, while

.CS
\fBexpr\fR {5 / 4.0}
\fBexpr\fR {5 / ( [string length "abcd"] + 0.0 )}
.CE

both return 1.25.
Floating-point values are always returned with a
.QW \fB.\fR
or an
.QW \fBe\fR
so that they will not look like integer values.  For example,

.CS
\fBexpr\fR {20.0/5.0}
.CE

returns \fB4.0\fR, not \fB4\fR.
.SS "STRING OPERATIONS"
.PP
String values may be used as operands of the comparison operators,
although the expression evaluator tries to do comparisons as integer
or floating-point when it can,
i.e., when all arguments to the operator allow numeric interpretations,
except in the case of the \fBeq\fR and \fBne\fR operators.
If one of the operands of a comparison is a string and the other
has a numeric value, a canonical string representation of the numeric
operand value is generated to compare with the string operand.
Canonical string representation for integer values is a decimal string
format.  Canonical string representation for floating-point values
is that produced by the \fB%g\fR format specifier of Tcl's
\fBformat\fR command.  For example, the commands

.CS
\fBexpr {"0x03" > "2"}\fR
\fBexpr {"0y" > "0x12"}\fR
.CE

both return 1.  The first comparison is done using integer
comparison, and the second is done using string comparison.
Because of Tcl's tendency to treat values as numbers whenever
possible, it is not generally a good idea to use operators like \fB==\fR
when you really want string comparison and the values of the
operands could be arbitrary;  it is better in these cases to use
the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead.
.SH "PERFORMANCE CONSIDERATIONS"
.PP
Enclose expressions in braces for the best speed and the smallest
storage requirements.
This allows the Tcl bytecode compiler to generate the best code.
.PP
As mentioned above, expressions are substituted twice:
once by the Tcl parser and once by the \fBexpr\fR command.
For example, the commands

.CS
\fBset a 3\fR
\fBset b {$a + 2}\fR
\fBexpr $b*4\fR
.CE

return 11, not a multiple of 4.
This is because the Tcl parser will first substitute \fB$a + 2\fR for

the variable \fBb\fR,
then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR.

.PP
Most expressions do not require a second round of substitutions.
Either they are enclosed in braces or, if not,
their variable and command substitutions yield numbers or strings
that do not themselves require substitutions.
However, because a few unbraced expressions 
need two rounds of substitutions,
the bytecode compiler must emit
additional instructions to handle this situation.
The most expensive code is required for
unbraced expressions that contain command substitutions.
These expressions must be implemented by generating new code
each time the expression is executed.















.VS 8.5
When the expression is unbraced to allow the substitution of a function or
operator, consider using the commands documented in the \fBmathfunc\fR(n) or
\fBmathop\fR(n) manual pages directly instead.
.VE 8.5
.SH EXAMPLES
Define a procedure that computes an
.QW interesting
mathematical function:

.CS
proc tcl::mathfunc::calc {x y} {
    \fBexpr\fR { ($x**2 - $y**2) / exp($x**2 + $y**2) }
}
.CE
.PP
Convert polar coordinates into cartesian coordinates:

.CS
# convert from ($radius,$angle)
set x [\fBexpr\fR { $radius * cos($angle) }]
set y [\fBexpr\fR { $radius * sin($angle) }]
.CE
.PP
Convert cartesian coordinates into polar coordinates:

.CS
# convert from ($x,$y)
set radius [\fBexpr\fR { hypot($y, $x) }]
set angle  [\fBexpr\fR { atan2($y, $x) }]
.CE
.PP
Print a message describing the relationship of two string values to
each other:

.CS
puts "a and b are [\fBexpr\fR {$a eq $b ? {equal} : {different}}]"
.CE
.PP
Set a variable to whether an environment variable is both defined at
all and also set to a true boolean value:

.CS
set isTrue [\fBexpr\fR {
    [info exists ::env(SOME_ENV_VAR)] &&
    [string is true -strict $::env(SOME_ENV_VAR)]
}]
.CE
.PP
Generate a random integer in the range 0..99 inclusive:

.CS
set randNum [\fBexpr\fR { int(100 * rand()) }]
.CE
.SH "SEE ALSO"
array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n),
string(n), Tcl(n), while(n)
.SH KEYWORDS

Changes to doc/file.n.

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
.TP
\fBfile attributes \fIname\fR
.TP
\fBfile attributes \fIname\fR ?\fBoption\fR?
.TP
\fBfile attributes \fIname\fR ?\fBoption value option value...\fR?
.
This subcommand returns or sets platform-specific values associated
with a file. The first form returns a list of the platform-specific
options and their values. The second form returns the value for the
given option. The third form sets one or more of the values. The values
are as follows:
.RS
.PP
On Unix, \fB\-group\fR gets or sets the group name for the file. A
group id can be given to the command, but it returns a group name.
\fB\-owner\fR gets or sets the user name of the owner of the file. The
command returns the owner name, but the numerical id can be passed when
setting the owner. \fB\-permissions\fR retrieves or sets a file's
access permissions, using octal notation by default. This option also
provides limited support for setting permissions using the symbolic
notation accepted by the \fBchmod\fR command, following the form
[\fBugo\fR]?[[\fB+-=\fR][\fBrwxst\fR]\fB,\fR[...]]. Multiple permission

specifications may be given, separated by commas. E.g., \fBu+s,go-rw\fR
would set the setuid bit for a file's owner as well as remove read and
write permission for the file's group and other users. An
\fBls\fR-style string of the form \fBrwxrwxrwx\fR is also accepted but
must always be 9 characters long. E.g., \fBrwxr-xr-t\fR is equivalent
to \fB01755\fR. On versions of Unix supporting file flags,
\fB-readonly\fR returns the value of, or sets, or clears the readonly
attribute of a file, i.e., the user immutable flag (\fBuchg\fR) to the
\fBchflags\fR command.
.PP
On Windows, \fB\-archive\fR gives the value or sets or clears the
archive attribute of the file. \fB\-hidden\fR gives the value or sets
or clears the hidden attribute of the file. \fB\-longname\fR will
expand each path element to its long version. This attribute cannot be
set. \fB\-readonly\fR gives the value or sets or clears the readonly
attribute of the file. \fB\-shortname\fR gives a string where every







|
|
|
|
|


|
|
|
|
|
<
|
<
<
>
|
|
|
|
|
|
|
|
<







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
.TP
\fBfile attributes \fIname\fR
.TP
\fBfile attributes \fIname\fR ?\fBoption\fR?
.TP
\fBfile attributes \fIname\fR ?\fBoption value option value...\fR?
.
This subcommand returns or sets platform specific values associated
with a file. The first form returns a list of the platform specific
flags and their values. The second form returns the value for the
specific option. The third form sets one or more of the values. The
values are as follows:
.RS
.PP
On Unix, \fB\-group\fR gets or sets the group name for the file. A group id
can be given to the command, but it returns a group name. \fB\-owner\fR gets
or sets the user name of the owner of the file. The command returns the
owner name, but the numerical id can be passed when setting the
owner. \fB\-permissions\fR sets or retrieves the octal code that chmod(1)

uses.  This command does also has limited support for setting using the


symbolic attributes for chmod(1), of the form [ugo]?[[+\-=][rwxst],[...]],
where multiple symbolic attributes can be separated by commas (example:
\fBu+s,go\-rw\fR add sticky bit for user, remove read and write
permissions for group and other).  A simplified \fBls\fR style string,
of the form rwxrwxrwx (must be 9 characters), is also supported
(example: \fBrwxr\-xr\-t\fR is equivalent to 01755).
On versions of Unix supporting file flags, \fB\-readonly\fR gives the
value or sets or clears the readonly attribute of the file,
i.e. the user immutable flag \fBuchg\fR to chflags(1).

.PP
On Windows, \fB\-archive\fR gives the value or sets or clears the
archive attribute of the file. \fB\-hidden\fR gives the value or sets
or clears the hidden attribute of the file. \fB\-longname\fR will
expand each path element to its long version. This attribute cannot be
set. \fB\-readonly\fR gives the value or sets or clears the readonly
attribute of the file. \fB\-shortname\fR gives a string where every

Changes to doc/open.n.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
\fBb\fR added as the second or third character in the value to
indicate that the opened channel should be configured with the
\fB\-translation binary\fR option, making the channel suitable for 
reading or writing of binary data.
.VE 8.5
.PP
In the second form, \fIaccess\fR consists of a list of any of the
following flags, most of which have the standard POSIX meanings.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.
.TP 15
\fBRDONLY\fR
Open the file for reading only.
.TP 15
\fBWRONLY\fR
Open the file for writing only.







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
\fBb\fR added as the second or third character in the value to
indicate that the opened channel should be configured with the
\fB\-translation binary\fR option, making the channel suitable for 
reading or writing of binary data.
.VE 8.5
.PP
In the second form, \fIaccess\fR consists of a list of any of the
following flags, all of which have the standard POSIX meanings.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.
.TP 15
\fBRDONLY\fR
Open the file for reading only.
.TP 15
\fBWRONLY\fR
Open the file for writing only.
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
of the lines entered at the console will be sent to the command pipeline and
some will be sent to the Tcl evaluator.  If a command pipeline is opened for
writing, keystrokes entered into the console are not visible until the
pipe is closed.  These problems only occur because both Tcl and the child
application are competing for the console at the same time.  If the command
pipeline is started from a script, so that Tcl is not accessing the console,
or if the command pipeline does not use standard input or output, but is
redirected from or to a file, then the above problems do not occur.
.PP
Files opened in the
.QW \fBa\fR
mode or with the \fBAPPEND\fR flag set are implemented by seeking immediately
before each write, which is not an atomic operation and does not carry the
guarantee of strict appending that is present on POSIX platforms.
.RE
.TP
\fBUnix\fR\0\0\0\0\0\0\0
Valid values for \fIfileName\fR to open a serial port are generally of the
form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name
of any pseudo-file that maps to a serial port may be used.
Advanced configuration options are only supported for serial ports







|
<
<
<
<
<
<







347
348
349
350
351
352
353
354






355
356
357
358
359
360
361
of the lines entered at the console will be sent to the command pipeline and
some will be sent to the Tcl evaluator.  If a command pipeline is opened for
writing, keystrokes entered into the console are not visible until the
pipe is closed.  These problems only occur because both Tcl and the child
application are competing for the console at the same time.  If the command
pipeline is started from a script, so that Tcl is not accessing the console,
or if the command pipeline does not use standard input or output, but is
redirected from or to a file, then the above problems do not occur.  






.RE
.TP
\fBUnix\fR\0\0\0\0\0\0\0
Valid values for \fIfileName\fR to open a serial port are generally of the
form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name
of any pseudo-file that maps to a serial port may be used.
Advanced configuration options are only supported for serial ports
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
not accessing the console, or if the command pipeline does not use standard
input, but is redirected from a file, then the above problem does not occur.  
.RE
.PP
See the \fBPORTABILITY ISSUES\fR section of the \fBexec\fR command for
additional information not specific to command pipelines about executing
applications on the various platforms
.SH "EXAMPLES"
Open a file for writing, forcing it to be created and raising an error if it
already exists.
.PP
.CS
set myNewFile [\fBopen\fR filename.txt {WRONLY CREAT EXCL}]
.CE
.PP
Open a file for writing as a log file.
.PP
.CS
set myLogFile [\fBopen\fR filename.log "a"]
fconfigure $myLogFile -buffering line
.CE
.PP
Open a command pipeline and catch any errors:
.PP
.CS
set fl [\fBopen\fR "| ls this_file_does_not_exist"]
set data [read $fl]
if {[catch {close $fl} err]} {
    puts "ls command failed: $err"
}
.CE
.PP
Open a command pipeline and read binary data from it. Note the unusual form
with
.QW |[list
that handles non-trivial edge cases with arguments that potentially have
spaces in.
.PP
.CS
set fl [\fBopen\fR |[list create_image_data $input] "rb"]
set binData [read $fl]
close $fl
.CE
.SH "SEE ALSO"
file(n), close(n), filename(n), fconfigure(n), gets(n), read(n),
puts(n), exec(n), pid(n), fopen(3)
.SH KEYWORDS
access mode, append, create, file, non-blocking, open, permissions,
pipeline, process, serial







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<







<
<
<
<
<
<
<
<
<
<
<
<






372
373
374
375
376
377
378
379














380

381
382
383
384
385
386
387












388
389
390
391
392
393
not accessing the console, or if the command pipeline does not use standard
input, but is redirected from a file, then the above problem does not occur.  
.RE
.PP
See the \fBPORTABILITY ISSUES\fR section of the \fBexec\fR command for
additional information not specific to command pipelines about executing
applications on the various platforms
.SH "EXAMPLE"














Open a command pipeline and catch any errors:

.CS
set fl [\fBopen\fR "| ls this_file_does_not_exist"]
set data [read $fl]
if {[catch {close $fl} err]} {
    puts "ls command failed: $err"
}
.CE












.SH "SEE ALSO"
file(n), close(n), filename(n), fconfigure(n), gets(n), read(n),
puts(n), exec(n), pid(n), fopen(3)
.SH KEYWORDS
access mode, append, create, file, non-blocking, open, permissions,
pipeline, process, serial

Changes to doc/re_syntax.n.

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
are met. A constraint may not be followed by a quantifier. The
simple constraints are as follows; some more constraints are described
later, under \fBESCAPES\fR.
.RS 2
.TP 8
\fB^\fR
.
matches at the beginning of the string or a line (according to whether
matching is newline-sensitive or not, as described in \fBMATCHING\fR,
below).
.TP
\fB$\fR
.
matches at the end of the string or a line (according to whether
matching is newline-sensitive or not, as described in \fBMATCHING\fR,
below).
.RS
.PP
The difference between string and line matching modes is immaterial
when the string does not contain a newline character.  The \fB\eA\fR
and \fB\eZ\fR constraint escapes have a similar purpose but are
always constraints for the overall string.
.PP
The default newline-sensitivity depends on the command that uses the
regular expression, and can be overridden as described in
\fBMETASYNTAX\fR, below.
.RE
.TP
\fB(?=\fIre\fB)\fR
.
\fIpositive lookahead\fR (AREs only), matches at any point where a
substring matching \fIre\fR begins
.TP
\fB(?!\fIre\fB)\fR







|
<
<



|
<
<
<
<
<
<
<
<
<
<
<
<
<







131
132
133
134
135
136
137
138


139
140
141
142













143
144
145
146
147
148
149
are met. A constraint may not be followed by a quantifier. The
simple constraints are as follows; some more constraints are described
later, under \fBESCAPES\fR.
.RS 2
.TP 8
\fB^\fR
.
matches at the beginning of a line


.TP
\fB$\fR
.
matches at the end of a line













.TP
\fB(?=\fIre\fB)\fR
.
\fIpositive lookahead\fR (AREs only), matches at any point where a
substring matching \fIre\fR begins
.TP
\fB(?!\fIre\fB)\fR

Changes to doc/tcltest.n.

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
'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1998-1999 Scriptics Corporation
'\" Copyright (c) 2000 Ajuba Solutions
'\" Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "tcltest" n 2.5 tcltest "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tcltest \- Test harness support code and utilities
.SH SYNOPSIS
.nf
\fBpackage require tcltest\fR ?\fB2.5\fR?

\fBtcltest::test \fIname description\fR ?\fI\-option value ...\fR?
\fBtcltest::test \fIname description\fR ?\fIconstraints\fR? \fIbody result\fR

\fBtcltest::loadTestedCommands\fR
\fBtcltest::makeDirectory \fIname\fR ?\fIdirectory\fR?
\fBtcltest::removeDirectory \fIname\fR ?\fIdirectory\fR?
\fBtcltest::makeFile \fIcontents name\fR ?\fIdirectory\fR?
\fBtcltest::removeFile \fIname\fR ?\fIdirectory\fR?
\fBtcltest::viewFile \fIname\fR ?\fIdirectory\fR?
\fBtcltest::cleanupTests \fR?\fIrunningMultipleTests\fR?
\fBtcltest::runAllTests\fR

\fBtcltest::configure\fR
\fBtcltest::configure \fI\-option\fR
\fBtcltest::configure \fI\-option value\fR ?\fI\-option value ...\fR?
\fBtcltest::customMatch \fImode command\fR
\fBtcltest::testConstraint \fIconstraint\fR ?\fIvalue\fR?
\fBtcltest::outputChannel \fR?\fIchannelID\fR?
\fBtcltest::errorChannel \fR?\fIchannelID\fR?
\fBtcltest::interpreter \fR?\fIinterp\fR?

\fBtcltest::debug \fR?\fIlevel\fR?
\fBtcltest::errorFile \fR?\fIfilename\fR?
\fBtcltest::limitConstraints \fR?\fIboolean\fR?
\fBtcltest::loadFile \fR?\fIfilename\fR?
\fBtcltest::loadScript \fR?\fIscript\fR?
\fBtcltest::match \fR?\fIpatternList\fR?
\fBtcltest::matchDirectories \fR?\fIpatternList\fR?
\fBtcltest::matchFiles \fR?\fIpatternList\fR?
\fBtcltest::outputFile \fR?\fIfilename\fR?
\fBtcltest::preserveCore \fR?\fIlevel\fR?
\fBtcltest::singleProcess \fR?\fIboolean\fR?
\fBtcltest::skip \fR?\fIpatternList\fR?
\fBtcltest::skipDirectories \fR?\fIpatternList\fR?
\fBtcltest::skipFiles \fR?\fIpatternList\fR?
\fBtcltest::temporaryDirectory \fR?\fIdirectory\fR?
\fBtcltest::testsDirectory \fR?\fIdirectory\fR?
\fBtcltest::verbose \fR?\fIlevel\fR?

\fBtcltest::test \fIname description optionList\fR
\fBtcltest::bytestring \fIstring\fR
\fBtcltest::normalizeMsg \fImsg\fR
\fBtcltest::normalizePath \fIpathVar\fR
\fBtcltest::workingDirectory \fR?\fIdir\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBtcltest\fR package provides several utility commands useful
in the construction of test suites for code instrumented to be
run by evaluation of Tcl commands.  Notably the built-in commands









|
|







|
|
|
|
|

|
|
|
|
|
|

|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|







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
'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1998-1999 Scriptics Corporation
'\" Copyright (c) 2000 Ajuba Solutions
'\" Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
.TH "tcltest" n 2.3 tcltest "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tcltest \- Test harness support code and utilities
.SH SYNOPSIS
.nf
\fBpackage require tcltest ?2.3?\fR
.sp
\fBtcltest::test \fIname description ?option value ...?\fR
\fBtcltest::test \fIname description ?constraints? body result\fR
.sp
\fBtcltest::loadTestedCommands\fR
\fBtcltest::makeDirectory \fIname ?directory?\fR
\fBtcltest::removeDirectory \fIname ?directory?\fR
\fBtcltest::makeFile \fIcontents name ?directory?\fR
\fBtcltest::removeFile \fIname ?directory?\fR
\fBtcltest::viewFile \fIname ?directory?\fR
\fBtcltest::cleanupTests \fI?runningMultipleTests?\fR
\fBtcltest::runAllTests\fR
.sp
\fBtcltest::configure\fR
\fBtcltest::configure \fIoption\fR
\fBtcltest::configure \fIoption value ?option value ...?\fR
\fBtcltest::customMatch \fImode command\fR
\fBtcltest::testConstraint \fIconstraint ?value?\fR
\fBtcltest::outputChannel \fI?channelID?\fR
\fBtcltest::errorChannel \fI?channelID?\fR
\fBtcltest::interpreter \fI?interp?\fR
.sp
\fBtcltest::debug \fI?level?\fR
\fBtcltest::errorFile \fI?filename?\fR
\fBtcltest::limitConstraints \fI?boolean?\fR
\fBtcltest::loadFile \fI?filename?\fR
\fBtcltest::loadScript \fI?script?\fR
\fBtcltest::match \fI?patternList?\fR
\fBtcltest::matchDirectories \fI?patternList?\fR
\fBtcltest::matchFiles \fI?patternList?\fR
\fBtcltest::outputFile \fI?filename?\fR
\fBtcltest::preserveCore \fI?level?\fR
\fBtcltest::singleProcess \fI?boolean?\fR
\fBtcltest::skip \fI?patternList?\fR
\fBtcltest::skipDirectories \fI?patternList?\fR
\fBtcltest::skipFiles \fI?patternList?\fR
\fBtcltest::temporaryDirectory \fI?directory?\fR
\fBtcltest::testsDirectory \fI?directory?\fR
\fBtcltest::verbose \fI?level?\fR
.sp
\fBtcltest::test \fIname description optionList\fR
\fBtcltest::bytestring \fIstring\fR
\fBtcltest::normalizeMsg \fImsg\fR
\fBtcltest::normalizePath \fIpathVar\fR
\fBtcltest::workingDirectory \fI?dir?\fR
.fi
.BE
.SH DESCRIPTION
.PP
The \fBtcltest\fR package provides several utility commands useful
in the construction of test suites for code instrumented to be
run by evaluation of Tcl commands.  Notably the built-in commands
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
test suites.
.PP
See \fBCREATING TEST SUITES WITH TCLTEST\fR below for an extended example
of how to use the commands of \fBtcltest\fR to produce test suites
for your Tcl-enabled code.
.SH COMMANDS
.TP
\fBtest\fR \fIname description\fR ?\fI\-option value ...\fR?
.
Defines and possibly runs a test with the name \fIname\fR and
description \fIdescription\fR.  The name and description of a test
are used in messages reported by \fBtest\fR during the
test, as configured by the options of \fBtcltest\fR.  The
remaining \fIoption value\fR arguments to \fBtest\fR
define the test, including the scripts to run, the conditions
under which to run them, the expected result, and the means
by which the expected and actual results should be compared.
See \fBTESTS\fR below for a complete description of the valid
options and how they define a test.  The \fBtest\fR command
returns an empty string.
.TP
\fBtest\fR \fIname description\fR ?\fIconstraints\fR? \fIbody result\fR
.
This form of \fBtest\fR is provided to support test suites written
for version 1 of the \fBtcltest\fR package, and also a simpler
interface for a common usage.  It is the same as
.QW "\fBtest\fR \fIname description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" .
All other options to \fBtest\fR
take their default values.  When \fIconstraints\fR is omitted, this
form of \fBtest\fR can be distinguished from the first because
all \fIoption\fRs begin with
.QW \- .
.TP
\fBloadTestedCommands\fR
.
Evaluates in the caller's context the script specified by
\fBconfigure \-load\fR or \fBconfigure \-loadfile\fR.
Returns the result of that script evaluation, including any error
raised by the script.  Use this command and the related
configuration options to provide the commands to be tested to
the interpreter running the test suite.
.TP
\fBmakeFile\fR \fIcontents name\fR ?\fIdirectory\fR?
.
Creates a file named \fIname\fR relative to
directory \fIdirectory\fR and write \fIcontents\fR
to that file using the encoding \fBencoding system\fR.
If \fIcontents\fR does not end with a newline, a newline
will be appended so that the file named \fIname\fR
does end with a newline.  Because the system encoding is used,
this command is only suitable for making text files.
The file will be removed by the next evaluation
of \fBcleanupTests\fR, unless it is removed by
\fBremoveFile\fR first.  The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns the full path of the file created.  Use this command
to create any text file required by a test with contents as needed.
.TP
\fBremoveFile\fR \fIname\fR ?\fIdirectory\fR?
.
Forces the file referenced by \fIname\fR to be removed.  This file name
should be relative to \fIdirectory\fR.   The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete files
created by \fBmakeFile\fR.
.TP
\fBmakeDirectory\fR \fIname\fR ?\fIdirectory\fR?
.
Creates a directory named \fIname\fR relative to directory \fIdirectory\fR.
The directory will be removed by the next evaluation of \fBcleanupTests\fR,
unless it is removed by \fBremoveDirectory\fR first.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns the full path of the directory created.  Use this command
to create any directories that are required to exist by a test.
.TP
\fBremoveDirectory\fR \fIname\fR ?\fIdirectory\fR?
.
Forces the directory referenced by \fIname\fR to be removed. This
directory should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete any directories
created by \fBmakeDirectory\fR.
.TP
\fBviewFile\fR \fIfile\fR ?\fIdirectory\fR?
.
Returns the contents of \fIfile\fR, except for any
final newline, just as \fBread \-nonewline\fR would return.
This file name should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.  Use this command
as a convenient way to turn the contents of a file generated
by a test into the result of that test for matching against
an expected result.  The contents of the file are read using
the system encoding, so its usefulness is limited to text
files.
.TP
\fBcleanupTests\fR
.
Intended to clean up and summarize after several tests have been
run.  Typically called once per test file, at the end of the file
after all tests have been completed.  For best effectiveness, be
sure that the \fBcleanupTests\fR is evaluated even if an error
occurs earlier in the test file evaluation.
.RS
.PP
Prints statistics about the tests run and removes files that were
created by \fBmakeDirectory\fR and \fBmakeFile\fR since the
last \fBcleanupTests\fR.  Names of files and directories
in the directory \fBconfigure \-tmpdir\fR created since
the last \fBcleanupTests\fR, but not created by
\fBmakeFile\fR or \fBmakeDirectory\fR are printed
to \fBoutputChannel\fR.  This command also restores the original
shell environment, as described by the global \fBenv\fR
array. Returns an empty string.
.RE
.TP
\fBrunAllTests\fR
.
This is a master command meant to run an entire suite of tests,
spanning multiple files and/or directories, as governed by
the configurable options of \fBtcltest\fR.  See \fBRUNNING ALL TESTS\fR
below for a complete description of the many variations possible
with \fBrunAllTests\fR.
.SS "CONFIGURATION COMMANDS"
.TP
\fBconfigure\fR
.
Returns the list of configurable options supported by \fBtcltest\fR.
See \fBCONFIGURABLE OPTIONS\fR below for the full list of options,
their valid values, and their effect on \fBtcltest\fR operations.
.TP
\fBconfigure \fIoption\fR
.
Returns the current value of the supported configurable option \fIoption\fR.
Raises an error if \fIoption\fR is not a supported configurable option.
.TP
\fBconfigure \fIoption value\fR ?\fI\-option value ...\fR?
.
Sets the value of each configurable option \fIoption\fR to the
corresponding value \fIvalue\fR, in order.  Raises an error if
an \fIoption\fR is not a supported configurable option, or if
\fIvalue\fR is not a valid value for the corresponding \fIoption\fR,
or if a \fIvalue\fR is not provided.  When an error is raised, the
operation of \fBconfigure\fR is halted, and subsequent \fIoption value\fR
arguments are not processed.
.RS
.PP
If the environment variable \fB::env(TCLTEST_OPTIONS)\fR exists when
the \fBtcltest\fR package is loaded (by \fBpackage require\fR \fBtcltest\fR)
then its value is taken as a list of arguments to pass to \fBconfigure\fR.
This allows the default values of the configuration options to be
set by the environment.
.RE
.TP
\fBcustomMatch \fImode script\fR
.
Registers \fImode\fR as a new legal value of the \fB\-match\fR option
to \fBtest\fR.  When the \fB\-match \fImode\fR option is
passed to \fBtest\fR, the script \fIscript\fR will be evaluated
to compare the actual result of evaluating the body of the test
to the expected result.
To perform the match, the \fIscript\fR is completed with two additional
words, the expected result, and the actual result, and the completed script
is evaluated in the global namespace.
The completed script is expected to return a boolean value indicating
whether or not the results match.  The built-in matching modes of
\fBtest\fR are \fBexact\fR, \fBglob\fR, and \fBregexp\fR.
.TP
\fBtestConstraint \fIconstraint\fR ?\fIboolean\fR?
.
Sets or returns the boolean value associated with the named \fIconstraint\fR.
See \fBTEST CONSTRAINTS\fR below for more information.
.TP
\fBinterpreter\fR ?\fIexecutableName\fR?
.
Sets or returns the name of the executable to be \fBexec\fRed by
\fBrunAllTests\fR to run each test file when
\fBconfigure \-singleproc\fR is false.
The default value for \fBinterpreter\fR is the name of the
currently running program as returned by \fBinfo nameofexecutable\fR.
.TP
\fBoutputChannel\fR ?\fIchannelID\fR?
.
Sets or returns the output channel ID.  This defaults to \fBstdout\fR.
Any test that prints test related output should send
that output to \fBoutputChannel\fR rather than letting
that output default to \fBstdout\fR.
.TP
\fBerrorChannel\fR ?\fIchannelID\fR?
.
Sets or returns the error channel ID.  This defaults to \fBstderr\fR.
Any test that prints error messages should send
that output to \fBerrorChannel\fR rather than printing
directly to \fBstderr\fR.
.SS "SHORTCUT CONFIGURATION COMMANDS"
.TP
\fBdebug\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-debug\fR ?\fIlevel\fR?" .
.TP
\fBerrorFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-errfile\fR ?\fIfilename\fR?" .
.TP
\fBlimitConstraints\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-limitconstraints\fR ?\fIboolean\fR?" .
.TP
\fBloadFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-loadfile\fR ?\fIfilename\fR?" .
.TP
\fBloadScript\fR ?\fIscript\fR?
.
Same as
.QW "\fBconfigure \-load\fR ?\fIscript\fR?" .
.TP
\fBmatch\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-match\fR ?\fIpatternList\fR?" .
.TP
\fBmatchDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-relateddir\fR ?\fIpatternList\fR?" .
.TP
\fBmatchFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-file\fR ?\fIpatternList\fR?" .
.TP
\fBoutputFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-outfile\fR ?\fIfilename\fR?" .
.TP
\fBpreserveCore\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-preservecore\fR ?\fIlevel\fR?" .
.TP
\fBsingleProcess\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-singleproc\fR ?\fIboolean\fR?" .
.TP
\fBskip\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-skip\fR ?\fIpatternList\fR?" .
.TP
\fBskipDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-asidefromdir\fR ?\fIpatternList\fR?" .
.TP
\fBskipFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-notfile\fR ?\fIpatternList\fR?" .
.TP
\fBtemporaryDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-tmpdir\fR ?\fIdirectory\fR?" .
.TP
\fBtestsDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-testdir\fR ?\fIdirectory\fR?" .
.TP
\fBverbose\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-verbose\fR ?\fIlevel\fR?" .
.SS "OTHER COMMANDS"
.PP
The remaining commands provided by \fBtcltest\fR have better
alternatives provided by \fBtcltest\fR or \fBTcl\fR itself.  They
are retained to support existing test suites, but should be avoided
in new code.
.TP
\fBtest\fR \fIname description optionList\fR
.
This form of \fBtest\fR was provided to enable passing many
options spanning several lines to \fBtest\fR as a single
argument quoted by braces, rather than needing to backslash quote
the newlines between arguments to \fBtest\fR.  The \fIoptionList\fR
argument is expected to be a list with an even number of elements
representing \fIoption\fR and \fIvalue\fR arguments to pass
to \fBtest\fR.  However, these values are not passed directly, as







|
<












|
<











<
|






|
<














|
<






|
<








|
<







|
<












<














|




<





|


<





<



|
<










|






<












|
<



|
<






|
<
|


|

|
<
|


|
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|
<
<
|
|
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|

|
<
<
|
|







<







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
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147

148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203

204
205
206
207
208

209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245
246

247
248
249
250
251
252
253

254
255
256
257
258
259

260
261
262
263
264
265
266


267
268
269


270
271
272


273
274
275


276
277
278


279
280
281


282
283
284


285
286
287


288


289
290
291
292
293


294
295
296


297
298
299


300
301
302


303
304
305


306
307
308


309
310
311


312
313
314


315
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
test suites.
.PP
See \fBCREATING TEST SUITES WITH TCLTEST\fR below for an extended example
of how to use the commands of \fBtcltest\fR to produce test suites
for your Tcl-enabled code.
.SH COMMANDS
.TP
\fBtest\fR \fIname description ?option value ...?\fR

Defines and possibly runs a test with the name \fIname\fR and
description \fIdescription\fR.  The name and description of a test
are used in messages reported by \fBtest\fR during the
test, as configured by the options of \fBtcltest\fR.  The
remaining \fIoption value\fR arguments to \fBtest\fR
define the test, including the scripts to run, the conditions
under which to run them, the expected result, and the means
by which the expected and actual results should be compared.
See \fBTESTS\fR below for a complete description of the valid
options and how they define a test.  The \fBtest\fR command
returns an empty string.
.TP
\fBtest\fR \fIname description ?constraints? body result\fR

This form of \fBtest\fR is provided to support test suites written
for version 1 of the \fBtcltest\fR package, and also a simpler
interface for a common usage.  It is the same as
.QW "\fBtest\fR \fIname description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" .
All other options to \fBtest\fR
take their default values.  When \fIconstraints\fR is omitted, this
form of \fBtest\fR can be distinguished from the first because
all \fIoption\fRs begin with
.QW \- .
.TP
\fBloadTestedCommands\fR

Evaluates in the caller's context the script specified by 
\fBconfigure \-load\fR or \fBconfigure \-loadfile\fR.
Returns the result of that script evaluation, including any error
raised by the script.  Use this command and the related
configuration options to provide the commands to be tested to
the interpreter running the test suite.
.TP
\fBmakeFile\fR \fIcontents name ?directory?\fR

Creates a file named \fIname\fR relative to
directory \fIdirectory\fR and write \fIcontents\fR
to that file using the encoding \fBencoding system\fR.
If \fIcontents\fR does not end with a newline, a newline
will be appended so that the file named \fIname\fR
does end with a newline.  Because the system encoding is used,
this command is only suitable for making text files.
The file will be removed by the next evaluation
of \fBcleanupTests\fR, unless it is removed by
\fBremoveFile\fR first.  The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns the full path of the file created.  Use this command
to create any text file required by a test with contents as needed.
.TP
\fBremoveFile\fR \fIname ?directory?\fR

Forces the file referenced by \fIname\fR to be removed.  This file name
should be relative to \fIdirectory\fR.   The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete files
created by \fBmakeFile\fR.
.TP
\fBmakeDirectory\fR \fIname ?directory?\fR

Creates a directory named \fIname\fR relative to directory \fIdirectory\fR.
The directory will be removed by the next evaluation of \fBcleanupTests\fR,
unless it is removed by \fBremoveDirectory\fR first.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns the full path of the directory created.  Use this command
to create any directories that are required to exist by a test.
.TP
\fBremoveDirectory\fR \fIname ?directory?\fR

Forces the directory referenced by \fIname\fR to be removed. This
directory should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete any directories
created by \fBmakeDirectory\fR.
.TP
\fBviewFile\fR \fIfile ?directory?\fR

Returns the contents of \fIfile\fR, except for any
final newline, just as \fBread \-nonewline\fR would return.
This file name should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.  Use this command
as a convenient way to turn the contents of a file generated
by a test into the result of that test for matching against
an expected result.  The contents of the file are read using
the system encoding, so its usefulness is limited to text
files.
.TP
\fBcleanupTests\fR

Intended to clean up and summarize after several tests have been
run.  Typically called once per test file, at the end of the file
after all tests have been completed.  For best effectiveness, be
sure that the \fBcleanupTests\fR is evaluated even if an error
occurs earlier in the test file evaluation.
.RS
.PP
Prints statistics about the tests run and removes files that were
created by \fBmakeDirectory\fR and \fBmakeFile\fR since the
last \fBcleanupTests\fR.  Names of files and directories
in the directory \fBconfigure \-tmpdir\fR created since
the last \fBcleanupTests\fR, but not created by
\fBmakeFile\fR or \fBmakeDirectory\fR are printed
to \fBoutputChannel\fR.  This command also restores the original
shell environment, as described by the \fB::env\fR
array. Returns an empty string.
.RE
.TP
\fBrunAllTests\fR

This is a master command meant to run an entire suite of tests,
spanning multiple files and/or directories, as governed by
the configurable options of \fBtcltest\fR.  See \fBRUNNING ALL TESTS\fR
below for a complete description of the many variations possible
with \fBrunAllTests\fR.
.SH "CONFIGURATION COMMANDS"
.TP
\fBconfigure\fR

Returns the list of configurable options supported by \fBtcltest\fR.
See \fBCONFIGURABLE OPTIONS\fR below for the full list of options,
their valid values, and their effect on \fBtcltest\fR operations.
.TP
\fBconfigure \fIoption\fR

Returns the current value of the supported configurable option \fIoption\fR.
Raises an error if \fIoption\fR is not a supported configurable option.
.TP
\fBconfigure \fIoption value ?option value ...?\fR

Sets the value of each configurable option \fIoption\fR to the
corresponding value \fIvalue\fR, in order.  Raises an error if
an \fIoption\fR is not a supported configurable option, or if
\fIvalue\fR is not a valid value for the corresponding \fIoption\fR,
or if a \fIvalue\fR is not provided.  When an error is raised, the
operation of \fBconfigure\fR is halted, and subsequent \fIoption value\fR
arguments are not processed.
.RS
.PP
If the environment variable \fB::env(TCLTEST_OPTIONS)\fR exists when
the \fBtcltest\fR package is loaded (by \fBpackage require tcltest\fR)
then its value is taken as a list of arguments to pass to \fBconfigure\fR.
This allows the default values of the configuration options to be
set by the environment.
.RE
.TP
\fBcustomMatch \fImode script\fR

Registers \fImode\fR as a new legal value of the \fB\-match\fR option
to \fBtest\fR.  When the \fB\-match \fImode\fR option is
passed to \fBtest\fR, the script \fIscript\fR will be evaluated
to compare the actual result of evaluating the body of the test
to the expected result.
To perform the match, the \fIscript\fR is completed with two additional
words, the expected result, and the actual result, and the completed script
is evaluated in the global namespace.
The completed script is expected to return a boolean value indicating
whether or not the results match.  The built-in matching modes of
\fBtest\fR are \fBexact\fR, \fBglob\fR, and \fBregexp\fR.
.TP
\fBtestConstraint \fIconstraint ?boolean?\fR

Sets or returns the boolean value associated with the named \fIconstraint\fR.
See \fBTEST CONSTRAINTS\fR below for more information.
.TP
\fBinterpreter\fR \fI?executableName?\fR

Sets or returns the name of the executable to be \fBexec\fRed by
\fBrunAllTests\fR to run each test file when
\fBconfigure \-singleproc\fR is false.
The default value for \fBinterpreter\fR is the name of the
currently running program as returned by \fBinfo nameofexecutable\fR.
.TP
\fBoutputChannel\fR \fI?channelID?\fR

Sets or returns the output channel ID.  This defaults to stdout.
Any test that prints test related output should send
that output to \fBoutputChannel\fR rather than letting
that output default to stdout.
.TP
\fBerrorChannel\fR \fI?channelID?\fR

Sets or returns the error channel ID.  This defaults to stderr.
Any test that prints error messages should send
that output to \fBerrorChannel\fR rather than printing
directly to stderr.
.SH "SHORTCUT COMMANDS"
.TP
\fBdebug \fI?level?\fR


Same as \fBconfigure \-debug \fI?level?\fR.
.TP
\fBerrorFile \fI?filename?\fR


Same as \fBconfigure \-errfile \fI?filename?\fR.
.TP
\fBlimitConstraints \fI?boolean?\fR


Same as \fBconfigure \-limitconstraints \fI?boolean?\fR.
.TP
\fBloadFile \fI?filename?\fR


Same as \fBconfigure \-loadfile \fI?filename?\fR.
.TP
\fBloadScript \fI?script?\fR


Same as \fBconfigure \-load \fI?script?\fR.
.TP
\fBmatch \fI?patternList?\fR


Same as \fBconfigure \-match \fI?patternList?\fR.
.TP
\fBmatchDirectories \fI?patternList?\fR


Same as \fBconfigure \-relateddir \fI?patternList?\fR.
.TP
\fBmatchFiles \fI?patternList?\fR


Same as \fBconfigure \-file \fI?patternList?\fR.


.TP
\fBoutputFile \fI?filename?\fR
Same as \fBconfigure \-outfile \fI?filename?\fR.
.TP
\fBpreserveCore \fI?level?\fR


Same as \fBconfigure \-preservecore \fI?level?\fR.
.TP
\fBsingleProcess \fI?boolean?\fR


Same as \fBconfigure \-singleproc \fI?boolean?\fR.
.TP
\fBskip \fI?patternList?\fR


Same as \fBconfigure \-skip \fI?patternList?\fR.
.TP
\fBskipDirectories \fI?patternList?\fR


Same as \fBconfigure \-asidefromdir \fI?patternList?\fR.
.TP
\fBskipFiles \fI?patternList?\fR


Same as \fBconfigure \-notfile \fI?patternList?\fR.
.TP
\fBtemporaryDirectory \fI?directory?\fR


Same as \fBconfigure \-tmpdir \fI?directory?\fR.
.TP
\fBtestsDirectory \fI?directory?\fR


Same as \fBconfigure \-testdir \fI?directory?\fR.
.TP
\fBverbose \fI?level?\fR


Same as \fBconfigure \-verbose \fI?level?\fR.
.SH "OTHER COMMANDS"
.PP
The remaining commands provided by \fBtcltest\fR have better
alternatives provided by \fBtcltest\fR or \fBTcl\fR itself.  They
are retained to support existing test suites, but should be avoided
in new code.
.TP
\fBtest\fR \fIname description optionList\fR

This form of \fBtest\fR was provided to enable passing many
options spanning several lines to \fBtest\fR as a single
argument quoted by braces, rather than needing to backslash quote
the newlines between arguments to \fBtest\fR.  The \fIoptionList\fR
argument is expected to be a list with an even number of elements
representing \fIoption\fR and \fIvalue\fR arguments to pass
to \fBtest\fR.  However, these values are not passed directly, as
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
\fBCREATING TEST SUITES WITH TCLTEST\fR below to see that this
form is really not necessary to avoid backslash-quoted newlines.
If you insist on using this form, examine
the source code of \fBtcltest\fR if you want to know the substitution
details, or just enclose the third through last argument
to \fBtest\fR in braces and hope for the best.
.TP
\fBworkingDirectory\fR ?\fIdirectoryName\fR?
.
Sets or returns the current working directory when the test suite is
running.  The default value for workingDirectory is the directory in
which the test suite was launched.  The Tcl commands \fBcd\fR and
\fBpwd\fR are sufficient replacements.
.TP
\fBnormalizeMsg \fImsg\fR
.
Returns the result of removing the
.QW extra
newlines from \fImsg\fR, where
.QW extra
is rather imprecise.  Tcl offers plenty of string
processing commands to modify strings as you wish, and
\fBcustomMatch\fR allows flexible matching of actual and expected
results.
.TP
\fBnormalizePath \fIpathVar\fR
.
Resolves symlinks in a path, thus creating a path without internal
redirection.  It is assumed that \fIpathVar\fR is absolute.
\fIpathVar\fR is modified in place.  The Tcl command \fBfile normalize\fR
is a sufficient replacement.
.TP
\fBbytestring \fIstring\fR
.
Construct a string that consists of the requested sequence of bytes,
as opposed to a string of properly formed UTF-8 characters using the
value supplied in \fIstring\fR.  This allows the tester to create
denormalized or improperly formed strings to pass to C procedures that
are supposed to accept strings with embedded NULL types and confirm
that a string result has a certain pattern of bytes.  This is
exactly equivalent to the Tcl command \fBencoding convertfrom\fR
\fBidentity\fR.
.SH TESTS
.PP
The \fBtest\fR command is the heart of the \fBtcltest\fR package.
Its essential function is to evaluate a Tcl script and compare
the result with an expected result.  The options of \fBtest\fR
define the test script, the environment in which to evaluate it,
the expected result, and how the compare the actual result to
the expected result.  Some configuration options of \fBtcltest\fR
also influence how \fBtest\fR operates.
.PP
The valid options for \fBtest\fR are summarized:
.PP
.CS
\fBtest\fR \fIname\fR \fIdescription\fR
        ?\fB\-constraints \fIkeywordList|expression\fR?
        ?\fB\-setup \fIsetupScript\fR?
        ?\fB\-body \fItestScript\fR?
        ?\fB\-cleanup \fIcleanupScript\fR?
        ?\fB\-result \fIexpectedAnswer\fR?
        ?\fB\-output \fIexpectedOutput\fR?
        ?\fB\-errorOutput \fIexpectedError\fR?
        ?\fB\-returnCodes \fIcodeList\fR?
        ?\fB\-errorCode \fIexpectedErrorCode\fR?
        ?\fB\-match \fImode\fR?
.CE
.PP
The \fIname\fR may be any string.  It is conventional to choose
a \fIname\fR according to the pattern:
.PP
.CS
\fItarget\fR-\fImajorNum\fR.\fIminorNum\fR







|
<





|
<









|
<





|
<






|
<














|
|
|
|
|
|
|
|
<
|







340
341
342
343
344
345
346
347

348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369

370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
\fBCREATING TEST SUITES WITH TCLTEST\fR below to see that this
form is really not necessary to avoid backslash-quoted newlines.
If you insist on using this form, examine
the source code of \fBtcltest\fR if you want to know the substitution
details, or just enclose the third through last argument
to \fBtest\fR in braces and hope for the best.
.TP
\fBworkingDirectory\fR \fI?directoryName?\fR

Sets or returns the current working directory when the test suite is
running.  The default value for workingDirectory is the directory in
which the test suite was launched.  The Tcl commands \fBcd\fR and
\fBpwd\fR are sufficient replacements.
.TP
\fBnormalizeMsg\fR \fImsg\fR

Returns the result of removing the
.QW extra
newlines from \fImsg\fR, where
.QW extra
is rather imprecise.  Tcl offers plenty of string
processing commands to modify strings as you wish, and
\fBcustomMatch\fR allows flexible matching of actual and expected
results.
.TP
\fBnormalizePath\fR \fIpathVar\fR

Resolves symlinks in a path, thus creating a path without internal
redirection.  It is assumed that \fIpathVar\fR is absolute.
\fIpathVar\fR is modified in place.  The Tcl command \fBfile normalize\fR
is a sufficient replacement.
.TP
\fBbytestring\fR \fIstring\fR

Construct a string that consists of the requested sequence of bytes,
as opposed to a string of properly formed UTF-8 characters using the
value supplied in \fIstring\fR.  This allows the tester to create
denormalized or improperly formed strings to pass to C procedures that
are supposed to accept strings with embedded NULL types and confirm
that a string result has a certain pattern of bytes.  This is
exactly equivalent to the Tcl command \fBencoding convertfrom identity\fR.

.SH TESTS
.PP
The \fBtest\fR command is the heart of the \fBtcltest\fR package.
Its essential function is to evaluate a Tcl script and compare
the result with an expected result.  The options of \fBtest\fR
define the test script, the environment in which to evaluate it,
the expected result, and how the compare the actual result to
the expected result.  Some configuration options of \fBtcltest\fR
also influence how \fBtest\fR operates.
.PP
The valid options for \fBtest\fR are summarized:
.PP
.CS
\fBtest\fR \fIname\fR \fIdescription\fR
        ?-constraints \fIkeywordList|expression\fR?
        ?-setup \fIsetupScript\fR?
        ?-body \fItestScript\fR?
        ?-cleanup \fIcleanupScript\fR?
        ?-result \fIexpectedAnswer\fR?
        ?-output \fIexpectedOutput\fR?
        ?-errorOutput \fIexpectedError\fR?
        ?-returnCodes \fIcodeList\fR?

        ?-match \fImode\fR?
.CE
.PP
The \fIname\fR may be any string.  It is conventional to choose
a \fIname\fR according to the pattern:
.PP
.CS
\fItarget\fR-\fImajorNum\fR.\fIminorNum\fR
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
.PP
The \fIdescription\fR should be a short textual description of the
test.  The \fIdescription\fR is included in output produced by the
test, typically test failure messages.  Good \fIdescription\fR values
should briefly explain the purpose of the test to users of a test suite.
The name of a Tcl or C function being tested should be included in the
description for regression tests.  If the test case exists to reproduce
a bug, include the bug ID in the description.
.PP
Valid attributes and associated values are:
.TP
\fB\-constraints \fIkeywordList\fR|\fIexpression\fR
.
The optional \fB\-constraints\fR attribute can be list of one or more
keywords or an expression.  If the \fB\-constraints\fR value is a list of
keywords, each of these keywords should be the name of a constraint
defined by a call to \fBtestConstraint\fR.  If any of the listed
constraints is false or does not exist, the test is skipped.  If the
\fB\-constraints\fR value is an expression, that expression
is evaluated. If the expression evaluates to true, then the test is run.
Note that the expression form of \fB\-constraints\fR may interfere with the
operation of \fBconfigure \-constraints\fR and
\fBconfigure \-limitconstraints\fR, and is not recommended.
Appropriate constraints should be added to any tests that should
not always be run.  That is, conditional evaluation of a test
should be accomplished by the \fB\-constraints\fR option, not by
conditional evaluation of \fBtest\fR.  In that way, the same
number of tests are always reported by the test suite, though
the number skipped may change based on the testing environment.
The default value is an empty list.
See \fBTEST CONSTRAINTS\fR below for a list of built-in constraints
and information on how to add your own constraints.
.TP
\fB\-setup \fIscript\fR
.
The optional \fB\-setup\fR attribute indicates a \fIscript\fR that will be run
before the script indicated by the \fB\-body\fR attribute.  If evaluation
of \fIscript\fR raises an error, the test will fail.  The default value
is an empty script.
.TP
\fB\-body \fIscript\fR
.
The \fB\-body\fR attribute indicates the \fIscript\fR to run to carry out the
test, which must return a result that can be checked for correctness.
If evaluation of \fIscript\fR raises an error, the test will fail
(unless the \fB\-returnCodes\fR option is used to state that an error
is expected).
The default value is an empty script.
.TP
\fB\-cleanup \fIscript\fR
.
The optional \fB\-cleanup\fR attribute indicates a \fIscript\fR that will be
run after the script indicated by the \fB\-body\fR attribute.
If evaluation of \fIscript\fR raises an error, the test will fail.
The default value is an empty script.
.TP
\fB\-match \fImode\fR
.
The \fB\-match\fR attribute determines how expected answers supplied by
\fB\-result\fR, \fB\-output\fR, and \fB\-errorOutput\fR are compared.  Valid
values for \fImode\fR are \fBregexp\fR, \fBglob\fR, \fBexact\fR, and
any value registered by a prior call to \fBcustomMatch\fR.  The default
value is \fBexact\fR.
.TP
\fB\-result \fIexpectedValue\fR
.
The \fB\-result\fR attribute supplies the \fIexpectedValue\fR against which
the return value from script will be compared. The default value is
an empty string.
.TP
\fB\-output \fIexpectedValue\fR
.
The \fB\-output\fR attribute supplies the \fIexpectedValue\fR against which
any output sent to \fBstdout\fR or \fBoutputChannel\fR during evaluation
of the script(s) will be compared.  Note that only output printed using
the global \fBputs\fR command is used for comparison.  If \fB\-output\fR is
not specified, output sent to \fBstdout\fR and \fBoutputChannel\fR is not
processed for comparison.
.TP
\fB\-errorOutput \fIexpectedValue\fR
.
The \fB\-errorOutput\fR attribute supplies the \fIexpectedValue\fR against
which any output sent to \fBstderr\fR or \fBerrorChannel\fR during
evaluation of the script(s) will be compared. Note that only output
printed using the global \fBputs\fR command is used for comparison.  If
\fB\-errorOutput\fR is not specified, output sent to \fBstderr\fR and
\fBerrorChannel\fR is not processed for comparison.
.TP
\fB\-returnCodes \fIexpectedCodeList\fR
.
The optional \fB\-returnCodes\fR attribute supplies \fIexpectedCodeList\fR,
a list of return codes that may be accepted from evaluation of the
\fB\-body\fR script.  If evaluation of the \fB\-body\fR script returns
a code not in the \fIexpectedCodeList\fR, the test fails.  All
return codes known to \fBreturn\fR, in both numeric and symbolic
form, including extended return codes, are acceptable elements in
the \fIexpectedCodeList\fR.  Default value is
.QW "\fBok return\fR" .
.TP
\fB\-errorCode \fIexpectedErrorCode\fR
.
The optional \fB\-errorCode\fR attribute supplies \fIexpectedErrorCode\fR,
a glob pattern that should match the error code reported from evaluation of the
\fB\-body\fR script.  If evaluation of the \fB\-body\fR script returns
a code not matching \fIexpectedErrorCode\fR, the test fails.  Default value is
.QW "\fB*\fR" .
If \fB\-returnCodes\fR does not include \fBerror\fR it is set to \fBerror\fR.
.PP
To pass, a test must successfully evaluate its \fB\-setup\fR, \fB\-body\fR,
and \fB\-cleanup\fR scripts.  The return code of the \fB\-body\fR script and
its result must match expected values, and if specified, output and error
data from the test must match expected \fB\-output\fR and \fB\-errorOutput\fR
values.  If any of these conditions are not met, then the test fails.
Note that all scripts are evaluated in the context of the caller
of \fBtest\fR.
.PP
As long as \fBtest\fR is called with valid syntax and legal
values for all attributes, it will not raise an error.  Test
failures are instead reported as output written to \fBoutputChannel\fR.
In default operation, a successful test produces no output.  The output
messages produced by \fBtest\fR are controlled by the
\fBconfigure \-verbose\fR option as described in \fBCONFIGURABLE OPTIONS\fR
below.  Any output produced by the test scripts themselves should be
produced using \fBputs\fR to \fBoutputChannel\fR or
\fBerrorChannel\fR, so that users of the test suite may
easily capture output with the \fBconfigure \-outfile\fR and
\fBconfigure \-errfile\fR options, and so that the \fB\-output\fR
and \fB\-errorOutput\fR attributes work properly.
.SS "TEST CONSTRAINTS"
.PP
Constraints are used to determine whether or not a test should be skipped.
Each constraint has a name, which may be any string, and a boolean
value.  Each \fBtest\fR has a \fB\-constraints\fR value which is a
list of constraint names.  There are two modes of constraint control.
Most frequently, the default mode is used, indicated by a setting
of \fBconfigure \-limitconstraints\fR to false.  The test will run







|



|
<
















|
|



<






<
|
|
|
<
<



<






<







<





<



|
|
|


<

|

|
|
|


<







|
<
<
<
<
<
<
<
<
<
















|




|







424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456

457
458
459
460
461
462

463
464
465


466
467
468

469
470
471
472
473
474

475
476
477
478
479
480
481

482
483
484
485
486

487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510









511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
.PP
The \fIdescription\fR should be a short textual description of the
test.  The \fIdescription\fR is included in output produced by the
test, typically test failure messages.  Good \fIdescription\fR values
should briefly explain the purpose of the test to users of a test suite.
The name of a Tcl or C function being tested should be included in the
description for regression tests.  If the test case exists to reproduce
a bug, include the bug ID in the description. 
.PP
Valid attributes and associated values are:
.TP
\fB\-constraints \fIkeywordList|expression\fR

The optional \fB\-constraints\fR attribute can be list of one or more
keywords or an expression.  If the \fB\-constraints\fR value is a list of
keywords, each of these keywords should be the name of a constraint
defined by a call to \fBtestConstraint\fR.  If any of the listed
constraints is false or does not exist, the test is skipped.  If the
\fB\-constraints\fR value is an expression, that expression
is evaluated. If the expression evaluates to true, then the test is run.
Note that the expression form of \fB\-constraints\fR may interfere with the
operation of \fBconfigure \-constraints\fR and
\fBconfigure \-limitconstraints\fR, and is not recommended.
Appropriate constraints should be added to any tests that should
not always be run.  That is, conditional evaluation of a test
should be accomplished by the \fB\-constraints\fR option, not by
conditional evaluation of \fBtest\fR.  In that way, the same
number of tests are always reported by the test suite, though
the number skipped may change based on the testing environment.
The default value is an empty list.  
See \fBTEST CONSTRAINTS\fR below for a list of built-in constraints 
and information on how to add your own constraints.
.TP
\fB\-setup \fIscript\fR

The optional \fB\-setup\fR attribute indicates a \fIscript\fR that will be run
before the script indicated by the \fB\-body\fR attribute.  If evaluation
of \fIscript\fR raises an error, the test will fail.  The default value
is an empty script.
.TP
\fB\-body \fIscript\fR

The \fB\-body\fR attribute indicates the \fIscript\fR to run to carry out the 
test.  It must return a result that can be checked for correctness.
If evaluation of \fIscript\fR raises an error, the test will fail.


The default value is an empty script.
.TP
\fB\-cleanup \fIscript\fR

The optional \fB\-cleanup\fR attribute indicates a \fIscript\fR that will be
run after the script indicated by the \fB\-body\fR attribute.
If evaluation of \fIscript\fR raises an error, the test will fail.
The default value is an empty script.
.TP
\fB\-match \fImode\fR

The \fB\-match\fR attribute determines how expected answers supplied by
\fB\-result\fR, \fB\-output\fR, and \fB\-errorOutput\fR are compared.  Valid
values for \fImode\fR are \fBregexp\fR, \fBglob\fR, \fBexact\fR, and
any value registered by a prior call to \fBcustomMatch\fR.  The default
value is \fBexact\fR.
.TP
\fB\-result \fIexpectedValue\fR

The \fB\-result\fR attribute supplies the \fIexpectedValue\fR against which
the return value from script will be compared. The default value is
an empty string.
.TP
\fB\-output \fIexpectedValue\fR

The \fB\-output\fR attribute supplies the \fIexpectedValue\fR against which
any output sent to \fBstdout\fR or \fBoutputChannel\fR during evaluation
of the script(s) will be compared.  Note that only output printed using
\fB::puts\fR is used for comparison.  If \fB\-output\fR is not specified,
output sent to \fBstdout\fR and \fBoutputChannel\fR is not processed for
comparison.
.TP
\fB\-errorOutput \fIexpectedValue\fR

The \fB\-errorOutput\fR attribute supplies the \fIexpectedValue\fR against
which any output sent to \fBstderr\fR or \fBerrorChannel\fR during 
evaluation of the script(s) will be compared. Note that only output
printed using \fB::puts\fR is used for comparison.  If \fB\-errorOutput\fR
is not specified, output sent to \fBstderr\fR and \fBerrorChannel\fR is
not processed for comparison.
.TP
\fB\-returnCodes \fIexpectedCodeList\fR

The optional \fB\-returnCodes\fR attribute supplies \fIexpectedCodeList\fR,
a list of return codes that may be accepted from evaluation of the
\fB\-body\fR script.  If evaluation of the \fB\-body\fR script returns
a code not in the \fIexpectedCodeList\fR, the test fails.  All
return codes known to \fBreturn\fR, in both numeric and symbolic
form, including extended return codes, are acceptable elements in
the \fIexpectedCodeList\fR.  Default value is
.QW \fBok return\fR.









.PP
To pass, a test must successfully evaluate its \fB\-setup\fR, \fB\-body\fR,
and \fB\-cleanup\fR scripts.  The return code of the \fB\-body\fR script and
its result must match expected values, and if specified, output and error
data from the test must match expected \fB\-output\fR and \fB\-errorOutput\fR
values.  If any of these conditions are not met, then the test fails.
Note that all scripts are evaluated in the context of the caller
of \fBtest\fR.
.PP
As long as \fBtest\fR is called with valid syntax and legal
values for all attributes, it will not raise an error.  Test
failures are instead reported as output written to \fBoutputChannel\fR.
In default operation, a successful test produces no output.  The output
messages produced by \fBtest\fR are controlled by the
\fBconfigure \-verbose\fR option as described in \fBCONFIGURABLE OPTIONS\fR
below.  Any output produced by the test scripts themselves should be
produced using \fB::puts\fR to \fBoutputChannel\fR or
\fBerrorChannel\fR, so that users of the test suite may
easily capture output with the \fBconfigure \-outfile\fR and
\fBconfigure \-errfile\fR options, and so that the \fB\-output\fR
and \fB\-errorOutput\fR attributes work properly.
.SH "TEST CONSTRAINTS"
.PP
Constraints are used to determine whether or not a test should be skipped.
Each constraint has a name, which may be any string, and a boolean
value.  Each \fBtest\fR has a \fB\-constraints\fR value which is a
list of constraint names.  There are two modes of constraint control.
Most frequently, the default mode is used, indicated by a setting
of \fBconfigure \-limitconstraints\fR to false.  The test will run
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652

653
654



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR
options.
.PP
The following is a list of constraints pre-defined by the
\fBtcltest\fR package itself:
.TP
\fIsingleTestInterp\fR
.
This test can only be run if all test files are sourced into a single
interpreter.
.TP
\fIunix\fR
.
This test can only be run on any Unix platform.
.TP
\fIwin\fR
.
This test can only be run on any Windows platform.
.TP
\fInt\fR

.

This test can only be run on any Windows NT platform.
.TP



\fImac\fR
.
This test can only be run on any Mac platform.
.TP
\fIunixOrWin\fR
.
This test can only be run on a Unix or Windows platform.
.TP
\fImacOrWin\fR
.
This test can only be run on a Mac or Windows platform.
.TP
\fImacOrUnix\fR
.
This test can only be run on a Mac or Unix platform.
.TP
\fItempNotWin\fR
.
This test can not be run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fItempNotMac\fR
.
This test can not be run on a Mac.  This flag is used
to temporarily disable a test.
.TP
\fIunixCrash\fR
.
This test crashes if it is run on Unix.  This flag is used to temporarily
disable a test.
.TP
\fIwinCrash\fR
.
This test crashes if it is run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fImacCrash\fR
.
This test crashes if it is run on a Mac.  This flag is used to temporarily
disable a test.
.TP
\fIemptyTest\fR
.
This test is empty, and so not worth running, but it remains as a
place-holder for a test to be written in the future.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fIknownBug\fR
.
This test is known to fail and the bug is not yet fixed.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fInonPortable\fR
.
This test can only be run in some known development environment.
Some tests are inherently non-portable because they depend on things
like word length, file system configuration, window manager, etc.
This constraint has value false to cause tests to be skipped unless
the user specifies otherwise.
.TP
\fIuserInteraction\fR
.
This test requires interaction from the user.  This constraint has
value false to causes tests to be skipped unless the user specifies
otherwise.
.TP
\fIinteractive\fR
.
This test can only be run in if the interpreter is in interactive mode
(when the global tcl_interactive variable is set to 1).
.TP
\fInonBlockFiles\fR
.
This test can only be run if platform supports setting files into
nonblocking mode.
.TP
\fIasyncPipeClose\fR
.
This test can only be run if platform supports async flush and async close
on a pipe.
.TP
\fIunixExecs\fR
.
This test can only be run if this machine has Unix-style commands
\fBcat\fR, \fBecho\fR, \fBsh\fR, \fBwc\fR, \fBrm\fR, \fBsleep\fR,
\fBfgrep\fR, \fBps\fR, \fBchmod\fR, and \fBmkdir\fR available.
.TP
\fIhasIsoLocale\fR
.
This test can only be run if can switch to an ISO locale.
.TP
\fIroot\fR
.
This test can only run if Unix user is root.
.TP
\fInotRoot\fR
.
This test can only run if Unix user is not root.
.TP
\fIeformat\fR
.
This test can only run if app has a working version of sprintf with respect
to the
.QW e
format of floating-point numbers.
.TP
\fIstdio\fR
.
This test can only be run if \fBinterpreter\fR can be \fBopen\fRed
as a pipe.
.PP
The alternative mode of constraint control is enabled by setting
\fBconfigure \-limitconstraints\fR to true.  With that configuration
setting, all existing constraints other than those in the constraint
list returned by \fBconfigure \-constraints\fR are set to false.
When the value of \fBconfigure \-constraints\fR







<
|
<


<
|


<
|


>
|
>
|

>
>
>

<
|


<
|


<
|


<
|


<
|
|


<
|



<
|
|


<
|
|


<
|
|


<
|





<
|




<
|



|


<
|

|


<
|



<
|
|


<
|
|


<
|

|


<
|


<
|


<
|


<
|





<
|







553
554
555
556
557
558
559

560

561
562

563
564
565

566
567
568
569
570
571
572
573
574
575
576
577

578
579
580

581
582
583

584
585
586

587
588
589

590
591
592
593

594
595
596
597

598
599
600
601

602
603
604
605

606
607
608
609

610
611
612
613
614
615

616
617
618
619
620

621
622
623
624
625
626
627

628
629
630
631
632

633
634
635
636

637
638
639
640

641
642
643
644

645
646
647
648
649

650
651
652

653
654
655

656
657
658

659
660
661
662
663
664

665
666
667
668
669
670
671
672
by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR
options.
.PP
The following is a list of constraints pre-defined by the
\fBtcltest\fR package itself:
.TP
\fIsingleTestInterp\fR

test can only be run if all test files are sourced into a single interpreter

.TP
\fIunix\fR

test can only be run on any Unix platform
.TP
\fIwin\fR

test can only be run on any Windows platform
.TP
\fInt\fR
test can only be run on any Windows NT platform
.TP
\fI95\fR
test can only be run on any Windows 95 platform
.TP
\fI98\fR
test can only be run on any Windows 98 platform
.TP
\fImac\fR

test can only be run on any Mac platform
.TP
\fIunixOrWin\fR

test can only be run on a Unix or Windows platform
.TP
\fImacOrWin\fR

test can only be run on a Mac or Windows platform
.TP
\fImacOrUnix\fR

test can only be run on a Mac or Unix platform
.TP
\fItempNotWin\fR

test can not be run on Windows.  This flag is used to temporarily
disable a test. 
.TP
\fItempNotMac\fR

test can not be run on a Mac.  This flag is used
to temporarily disable a test.
.TP
\fIunixCrash\fR

test crashes if it is run on Unix.  This flag is used to temporarily
disable a test. 
.TP
\fIwinCrash\fR

test crashes if it is run on Windows.  This flag is used to temporarily
disable a test. 
.TP
\fImacCrash\fR

test crashes if it is run on a Mac.  This flag is used to temporarily
disable a test. 
.TP
\fIemptyTest\fR

test is empty, and so not worth running, but it remains as a
place-holder for a test to be written in the future.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fIknownBug\fR

test is known to fail and the bug is not yet fixed.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fInonPortable\fR

test can only be run in some known development environment.
Some tests are inherently non-portable because they depend on things
like word length, file system configuration, window manager, etc.
This constraint has value false to cause tests to be skipped unless
the user specifies otherwise.  
.TP
\fIuserInteraction\fR

test requires interaction from the user.  This constraint has
value false to causes tests to be skipped unless the user specifies
otherwise.  
.TP
\fIinteractive\fR

test can only be run in if the interpreter is in interactive mode 
(when the global tcl_interactive variable is set to 1).
.TP
\fInonBlockFiles\fR

test can only be run if platform supports setting files into
nonblocking mode 
.TP
\fIasyncPipeClose\fR

test can only be run if platform supports async flush and async close
on a pipe 
.TP
\fIunixExecs\fR

test can only be run if this machine has Unix-style commands
\fBcat\fR, \fBecho\fR, \fBsh\fR, \fBwc\fR, \fBrm\fR, \fBsleep\fR,
\fBfgrep\fR, \fBps\fR, \fBchmod\fR, and \fBmkdir\fR available
.TP
\fIhasIsoLocale\fR

test can only be run if can switch to an ISO locale
.TP
\fIroot\fR

test can only run if Unix user is root
.TP
\fInotRoot\fR

test can only run if Unix user is not root
.TP
\fIeformat\fR

test can only run if app has a working version of sprintf with respect
to the
.QW e
format of floating-point numbers.
.TP
\fIstdio\fR

test can only be run if \fBinterpreter\fR can be \fBopen\fRed
as a pipe.
.PP
The alternative mode of constraint control is enabled by setting
\fBconfigure \-limitconstraints\fR to true.  With that configuration
setting, all existing constraints other than those in the constraint
list returned by \fBconfigure \-constraints\fR are set to false.
When the value of \fBconfigure \-constraints\fR
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
\fBconfigure\fR -constraints knownBug \e
          -limitconstraints true \e
          -verbose pass
.CE
.PP
to run exactly those tests that exercise known bugs, and discover
whether any of them pass, indicating the bug had been fixed.
.SS "RUNNING ALL TESTS"
.PP
The single command \fBrunAllTests\fR is evaluated to run an entire
test suite, spanning many files and directories.  The configuration
options of \fBtcltest\fR control the precise operations.  The
\fBrunAllTests\fR command begins by printing a summary of its
configuration to \fBoutputChannel\fR.
.PP
Test files to be evaluated are sought in the directory
\fBconfigure \-testdir\fR.  The list of files in that directory
that match any of the patterns in \fBconfigure \-file\fR and
match none of the patterns in \fBconfigure \-notfile\fR is generated
and sorted.  Then each file will be evaluated in turn.  If
\fBconfigure \-singleproc\fR is true, then each file will
be \fBsource\fRd in the caller's context.  If it is false,
then a copy of \fBinterpreter\fR will be \fBexec\fR'd to
evaluate each file.  The multi-process operation is useful
when testing can cause errors so severe that a process
terminates.  Although such an error may terminate a child
process evaluating one file, the master process can continue
with the rest of the test suite.  In multi-process operation,
the configuration of \fBtcltest\fR in the master process is
passed to the child processes as command line arguments,
with the exception of \fBconfigure \-outfile\fR.  The
\fBrunAllTests\fR command in the







|
















|







681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
\fBconfigure\fR -constraints knownBug \e
          -limitconstraints true \e
          -verbose pass
.CE
.PP
to run exactly those tests that exercise known bugs, and discover
whether any of them pass, indicating the bug had been fixed.
.SH "RUNNING ALL TESTS"
.PP
The single command \fBrunAllTests\fR is evaluated to run an entire
test suite, spanning many files and directories.  The configuration
options of \fBtcltest\fR control the precise operations.  The
\fBrunAllTests\fR command begins by printing a summary of its
configuration to \fBoutputChannel\fR.
.PP
Test files to be evaluated are sought in the directory
\fBconfigure \-testdir\fR.  The list of files in that directory
that match any of the patterns in \fBconfigure \-file\fR and
match none of the patterns in \fBconfigure \-notfile\fR is generated
and sorted.  Then each file will be evaluated in turn.  If
\fBconfigure \-singleproc\fR is true, then each file will
be \fBsource\fRd in the caller's context.  If it is false,
then a copy of \fBinterpreter\fR will be \fBexec\fR'd to
evaluate each file.  The multi-process operation is useful
when testing can cause errors so severe that a process 
terminates.  Although such an error may terminate a child
process evaluating one file, the master process can continue
with the rest of the test suite.  In multi-process operation,
the configuration of \fBtcltest\fR in the master process is
passed to the child processes as command line arguments,
with the exception of \fBconfigure \-outfile\fR.  The
\fBrunAllTests\fR command in the
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
test files evaluated by a single \fBrunAllTests\fR
command.
.SH "CONFIGURABLE OPTIONS"
The \fBconfigure\fR command is used to set and query the configurable
options of \fBtcltest\fR.  The valid options are:
.TP
\fB\-singleproc \fIboolean\fR
.
Controls whether or not \fBrunAllTests\fR spawns a child process for
each test file.  No spawning when \fIboolean\fR is true.  Default
value is false.
.TP
\fB\-debug \fIlevel\fR
.
Sets the debug level to \fIlevel\fR, an integer value indicating how
much debugging information should be printed to \fBstdout\fR.  Note that
debug messages always go to \fBstdout\fR, independent of the value of
\fBconfigure \-outfile\fR.  Default value is 0.  Levels are defined as:
.RS
.IP 0 4
Do not display any debug information.
.IP 1
Display information regarding whether a test is skipped because it
does not match any of the tests that were specified using by
\fBconfigure \-match\fR (userSpecifiedNonMatch) or matches any of
the tests specified by \fBconfigure \-skip\fR (userSpecifiedSkip).  Also
print warnings about possible lack of cleanup or balance in test files.
Also print warnings about any re-use of test names.
.IP 2
Display the flag array parsed by the command line processor, the
contents of the global \fBenv\fR array, and all user-defined variables
that exist in the current namespace as they are used.
.IP 3
Display information regarding what individual procs in the test
harness are doing.
.RE
.TP
\fB\-verbose \fIlevel\fR
.
Sets the type of output verbosity desired to \fIlevel\fR,
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
\fBskip\fR, \fBstart\fR, \fBerror\fR, \fBline\fR, \fBmsec\fR and \fBusec\fR.
Default value is
.QW "\fBbody error\fR" .
Levels are defined as:
.RS
.IP "body (\fBb\fR)"
Display the body of failed tests
.IP "pass (\fBp\fR)"
Print output when a test passes
.IP "skip (\fBs\fR)"
Print output when a test is skipped
.IP "start (\fBt\fR)"
Print output whenever a test starts
.IP "error (\fBe\fR)"
Print errorInfo and errorCode, if they exist, when a test return code
does not match its expected return code
.IP "line (\fBl\fR)"
Print source file line information of failed tests
.IP "msec (\fBm\fR)"
Print each test's execution time in milliseconds
.IP "usec (\fBu\fR)"
Print each test's execution time in microseconds
.PP
Note that the \fBmsec\fR and \fBusec\fR verbosity levels are provided as
indicative measures only. They do not tackle the problem of repeatibility which
should be considered in performance tests or benchmarks. To use these verbosity
levels to thoroughly track performance degradations, consider wrapping your
test bodies with \fBtime\fR commands.
.PP
The single letter abbreviations noted above are also recognized
so that
.QW "\fBconfigure \-verbose pt\fR"
is the same as
.QW "\fBconfigure \-verbose {pass start}\fR" .
.RE
.TP
\fB\-preservecore \fIlevel\fR
.
Sets the core preservation level to \fIlevel\fR.  This level
determines how stringent checks for core files are.  Default
value is 0.  Levels are defined as:
.RS
.IP 0
No checking \(em do not check for core files at the end of each test
command, but do check for them in \fBrunAllTests\fR after all
test files have been evaluated.
.IP 1
Also check for core files at the end of each \fBtest\fR command.
.IP 2
Check for core files at all times described above, and save a
copy of each core file produced in \fBconfigure \-tmpdir\fR.
.RE
.TP
\fB\-limitconstraints \fIboolean\fR
.
Sets the mode by which \fBtest\fR honors constraints as described
in \fBTESTS\fR above.  Default value is false.
.TP
\fB\-constraints \fIlist\fR
.
Sets all the constraints in \fIlist\fR to true.  Also used in
combination with \fBconfigure \-limitconstraints true\fR to control an
alternative constraint mode as described in \fBTESTS\fR above.
Default value is an empty list.
.TP
\fB\-tmpdir \fIdirectory\fR
.
Sets the temporary directory to be used by \fBmakeFile\fR,
\fBmakeDirectory\fR, \fBviewFile\fR, \fBremoveFile\fR,
and \fBremoveDirectory\fR as the default directory where
temporary files and directories created by test files should
be created.  Default value is \fBworkingDirectory\fR.
.TP
\fB\-testdir \fIdirectory\fR
.
Sets the directory searched by \fBrunAllTests\fR for test files
and subdirectories.  Default value is \fBworkingDirectory\fR.
.TP
\fB\-file \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to evaluate.  Default value is
.QW \fB*.test\fR .
.TP
\fB\-notfile \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to skip.  Default value is
.QW \fBl.*.test\fR ,
so that any SCCS lock files are skipped.
.TP
\fB\-relateddir \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to search for an \fBall.tcl\fR file.  Default
value is
.QW \fB*\fR .
.TP
\fB\-asidefromdir \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to skip when searching for an \fBall.tcl\fR file.
Default value is an empty list.
.TP
\fB\-match \fIpatternList\fR
.
Set the list of patterns used by \fBtest\fR to determine whether
a test should be run.  Default value is
.QW \fB*\fR .
.TP
\fB\-skip \fIpatternList\fR
.
Set the list of patterns used by \fBtest\fR to determine whether
a test should be skipped.  Default value is an empty list.
.TP
\fB\-load \fIscript\fR
.
Sets a script to be evaluated by \fBloadTestedCommands\fR.
Default value is an empty script.
.TP
\fB\-loadfile \fIfilename\fR
.
Sets the filename from which to read a script to be evaluated
by \fBloadTestedCommands\fR.  This is an alternative to
\fB\-load\fR.  They cannot be used together.
.TP
\fB\-outfile \fIfilename\fR
.
Sets the file to which all output produced by tcltest should be
written.  A file named \fIfilename\fR will be \fBopen\fRed for writing,
and the resulting channel will be set as the value of \fBoutputChannel\fR.
.TP
\fB\-errfile \fIfilename\fR
.
Sets the file to which all error output produced by tcltest
should be written.  A file named \fIfilename\fR will be \fBopen\fRed
for writing, and the resulting channel will be set as the value
of \fBerrorChannel\fR.
.SH "CREATING TEST SUITES WITH TCLTEST"
.PP
The fundamental element of a test suite is the individual \fBtest\fR







<





<

|
|


|










|
|






<


|
<
|
|

|

|

|

|

|


|

<
<
<
<
|
<
<
<
<
<
<





<


<











|




<




<






<







<




<





<






<






<





<





<




<




<




|
<





<







744
745
746
747
748
749
750

751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798




799






800
801
802
803
804

805
806

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823
824
825
826

827
828
829
830
831
832

833
834
835
836
837
838
839

840
841
842
843

844
845
846
847
848

849
850
851
852
853
854

855
856
857
858
859
860

861
862
863
864
865

866
867
868
869
870

871
872
873
874

875
876
877
878

879
880
881
882
883

884
885
886
887
888

889
890
891
892
893
894
895
test files evaluated by a single \fBrunAllTests\fR
command.
.SH "CONFIGURABLE OPTIONS"
The \fBconfigure\fR command is used to set and query the configurable
options of \fBtcltest\fR.  The valid options are:
.TP
\fB\-singleproc \fIboolean\fR

Controls whether or not \fBrunAllTests\fR spawns a child process for
each test file.  No spawning when \fIboolean\fR is true.  Default
value is false.
.TP
\fB\-debug \fIlevel\fR

Sets the debug level to \fIlevel\fR, an integer value indicating how
much debugging information should be printed to stdout.  Note that
debug messages always go to stdout, independent of the value of
\fBconfigure \-outfile\fR.  Default value is 0.  Levels are defined as:
.RS
.IP 0
Do not display any debug information.
.IP 1
Display information regarding whether a test is skipped because it
does not match any of the tests that were specified using by
\fBconfigure \-match\fR (userSpecifiedNonMatch) or matches any of
the tests specified by \fBconfigure \-skip\fR (userSpecifiedSkip).  Also
print warnings about possible lack of cleanup or balance in test files.
Also print warnings about any re-use of test names.
.IP 2
Display the flag array parsed by the command line processor, the
contents of the ::env array, and all user-defined variables that exist
in the current namespace as they are used.
.IP 3
Display information regarding what individual procs in the test
harness are doing.
.RE
.TP
\fB\-verbose \fIlevel\fR

Sets the type of output verbosity desired to \fIlevel\fR,
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
\fBskip\fR, \fBstart\fR, \fBerror\fR and \fBline\fR.  Default value

is \fB{body error}\fR.
Levels are defined as: 
.RS
.IP "body (b)"
Display the body of failed tests
.IP "pass (p)"
Print output when a test passes
.IP "skip (s)"
Print output when a test is skipped
.IP "start (t)"
Print output whenever a test starts
.IP "error (e)"
Print errorInfo and errorCode, if they exist, when a test return code
does not match its expected return code
.IP "line (l)"
Print source file line information of failed tests




.RE






The single letter abbreviations noted above are also recognized
so that
.QW "\fBconfigure \-verbose pt\fR"
is the same as
.QW "\fBconfigure \-verbose {pass start}\fR" .

.TP
\fB\-preservecore \fIlevel\fR

Sets the core preservation level to \fIlevel\fR.  This level
determines how stringent checks for core files are.  Default
value is 0.  Levels are defined as:
.RS
.IP 0
No checking \(em do not check for core files at the end of each test
command, but do check for them in \fBrunAllTests\fR after all
test files have been evaluated.
.IP 1
Also check for core files at the end of each \fBtest\fR command.
.IP 2
Check for core files at all times described above, and save a 
copy of each core file produced in \fBconfigure \-tmpdir\fR.
.RE
.TP
\fB\-limitconstraints \fIboolean\fR

Sets the mode by which \fBtest\fR honors constraints as described
in \fBTESTS\fR above.  Default value is false.
.TP
\fB\-constraints \fIlist\fR

Sets all the constraints in \fIlist\fR to true.  Also used in
combination with \fBconfigure \-limitconstraints true\fR to control an
alternative constraint mode as described in \fBTESTS\fR above.
Default value is an empty list.
.TP
\fB\-tmpdir \fIdirectory\fR

Sets the temporary directory to be used by \fBmakeFile\fR,
\fBmakeDirectory\fR, \fBviewFile\fR, \fBremoveFile\fR,
and \fBremoveDirectory\fR as the default directory where
temporary files and directories created by test files should
be created.  Default value is \fBworkingDirectory\fR.
.TP
\fB\-testdir \fIdirectory\fR

Sets the directory searched by \fBrunAllTests\fR for test files
and subdirectories.  Default value is \fBworkingDirectory\fR.
.TP
\fB\-file \fIpatternList\fR

Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to evaluate.  Default value is
.QW \fB*.test\fR .
.TP
\fB\-notfile \fIpatternList\fR

Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to skip.  Default value is
.QW \fBl.*.test\fR ,
so that any SCCS lock files are skipped.
.TP
\fB\-relateddir \fIpatternList\fR

Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to search for an \fBall.tcl\fR file.  Default
value is
.QW \fB*\fR .
.TP
\fB\-asidefromdir \fIpatternList\fR

Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to skip when searching for an \fBall.tcl\fR file.
Default value is an empty list.
.TP
\fB\-match \fIpatternList\fR

Set the list of patterns used by \fBtest\fR to determine whether
a test should be run.  Default value is
.QW \fB*\fR .
.TP
\fB\-skip \fIpatternList\fR

Set the list of patterns used by \fBtest\fR to determine whether
a test should be skipped.  Default value is an empty list.
.TP
\fB\-load \fIscript\fR

Sets a script to be evaluated by \fBloadTestedCommands\fR.
Default value is an empty script.
.TP
\fB\-loadfile \fIfilename\fR

Sets the filename from which to read a script to be evaluated
by \fBloadTestedCommands\fR.  This is an alternative to
\fB\-load\fR.  They cannot be used together.
.TP
\fB\-outfile \fIfilename\fR 

Sets the file to which all output produced by tcltest should be
written.  A file named \fIfilename\fR will be \fBopen\fRed for writing,
and the resulting channel will be set as the value of \fBoutputChannel\fR.
.TP
\fB\-errfile \fIfilename\fR

Sets the file to which all error output produced by tcltest
should be written.  A file named \fIfilename\fR will be \fBopen\fRed
for writing, and the resulting channel will be set as the value
of \fBerrorChannel\fR.
.SH "CREATING TEST SUITES WITH TCLTEST"
.PP
The fundamental element of a test suite is the individual \fBtest\fR
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
    removeFile test
} -result $::tcl_platform(user)
.CE
.RE
.PP
At the next higher layer of organization, several \fBtest\fR commands
are gathered together into a single test file.  Test files should have
names with the
.QW \fB.test\fR
extension, because that is the default pattern
used by \fBrunAllTests\fR to find test files.  It is a good rule of
thumb to have one test file for each source code file of your project.
It is good practice to edit the test file and the source code file
together, keeping tests synchronized with code changes.
.PP
Most of the code in the test file should be the \fBtest\fR commands.
Use constraints to skip tests, rather than conditional evaluation
of \fBtest\fR.
.IP [5]
Recommended system for writing conditional tests, using constraints to
guard:
.RS







<
<
|




|







944
945
946
947
948
949
950


951
952
953
954
955
956
957
958
959
960
961
962
963
    removeFile test
} -result $::tcl_platform(user)
.CE
.RE
.PP
At the next higher layer of organization, several \fBtest\fR commands
are gathered together into a single test file.  Test files should have


names with the \fB.test\fR extension, because that is the default pattern
used by \fBrunAllTests\fR to find test files.  It is a good rule of
thumb to have one test file for each source code file of your project.
It is good practice to edit the test file and the source code file
together, keeping tests synchronized with code changes.
.PP 
Most of the code in the test file should be the \fBtest\fR commands.
Use constraints to skip tests, rather than conditional evaluation
of \fBtest\fR.
.IP [5]
Recommended system for writing conditional tests, using constraints to
guard:
.RS
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
.IP [6]
Discouraged system for writing conditional tests, using \fBif\fR to
guard:
.RS
.PP
.CS
if $myRequirement {
    \fBtest\fR badConditionalTest {} {
        #body
    } result
}
.CE
.RE
.PP
Use the \fB\-setup\fR and \fB\-cleanup\fR options to establish and release







|







972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
.IP [6]
Discouraged system for writing conditional tests, using \fBif\fR to
guard:
.RS
.PP
.CS
if $myRequirement {
    test badConditionalTest {} {
        #body
    } result
}
.CE
.RE
.PP
Use the \fB\-setup\fR and \fB\-cleanup\fR options to establish and release
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
provided by earlier releases of \fBtcltest\fR have not been documented
here.  They are no longer part of the supported public interface of
\fBtcltest\fR and should not be used in new test suites.  However,
to continue to support existing test suites written to the older
interface specifications, many of those deprecated commands and
variables still work as before.  For example, in many circumstances,
\fBconfigure\fR will be automatically called shortly after
\fBpackage require\fR \fBtcltest 2.1\fR succeeds with arguments
from the variable \fB::argv\fR.  This is to support test suites
that depend on the old behavior that \fBtcltest\fR was automatically
configured from command line arguments.  New test files should not
depend on this, but should explicitly include
.PP
.CS
eval \fB::tcltest::configure\fR $::argv
.CE
.PP
or
.PP
.CS
\fB::tcltest::configure\fR {*}$::argv
.CE
.PP
to establish a configuration from command line arguments.
.SH "KNOWN ISSUES"
There are two known issues related to nested evaluations of \fBtest\fR.
The first issue relates to the stack level in which test scripts are
executed.  Tests nested within other tests may be executed at the same
stack level as the outermost test.  For example, in the following code:
.PP
.CS
\fBtest\fR level-1.1 {level 1} {
    -body {
        \fBtest\fR level-2.1 {level 2} {
        }
    }
}
.CE
.PP
any script executed in level-2.1 may be executed at the same stack
level as the script defined for level-1.1.
.PP
In addition, while two \fBtest\fRs have been run, results will only
be reported by \fBcleanupTests\fR for tests at the same level as
test level-1.1.  However, test results for all tests run prior to
level-1.1 will be available when test level-2.1 runs.  What this
means is that if you try to access the test results for test level-2.1,
it will may say that







|









<
<
<
<
<
<





|











|







1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078






1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
provided by earlier releases of \fBtcltest\fR have not been documented
here.  They are no longer part of the supported public interface of
\fBtcltest\fR and should not be used in new test suites.  However,
to continue to support existing test suites written to the older
interface specifications, many of those deprecated commands and
variables still work as before.  For example, in many circumstances,
\fBconfigure\fR will be automatically called shortly after
\fBpackage require tcltest 2.1\fR succeeds with arguments
from the variable \fB::argv\fR.  This is to support test suites
that depend on the old behavior that \fBtcltest\fR was automatically
configured from command line arguments.  New test files should not
depend on this, but should explicitly include
.PP
.CS
eval \fB::tcltest::configure\fR $::argv
.CE
.PP






to establish a configuration from command line arguments.
.SH "KNOWN ISSUES"
There are two known issues related to nested evaluations of \fBtest\fR.
The first issue relates to the stack level in which test scripts are
executed.  Tests nested within other tests may be executed at the same
stack level as the outermost test.  For example, in the following code: 
.PP
.CS
\fBtest\fR level-1.1 {level 1} {
    -body {
        \fBtest\fR level-2.1 {level 2} {
        }
    }
}
.CE
.PP
any script executed in level-2.1 may be executed at the same stack
level as the script defined for level-1.1.  
.PP
In addition, while two \fBtest\fRs have been run, results will only
be reported by \fBcleanupTests\fR for tests at the same level as
test level-1.1.  However, test results for all tests run prior to
level-1.1 will be available when test level-2.1 runs.  What this
means is that if you try to access the test results for test level-2.1,
it will may say that
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
.QW n ,
.QW o ,
and
.QW p
refer to tests that were run at the same test level as test level-1.1.
.PP
Implementation of output and error comparison in the test command
depends on usage of \fBputs\fR in your application code.  Output is
intercepted by redefining the global \fBputs\fR command while the defined test
script is being run.  Errors thrown by C procedures or printed
directly from C applications will not be caught by the \fBtest\fR command.
Therefore, usage of the \fB\-output\fR and \fB\-errorOutput\fR
options to \fBtest\fR is useful only for pure Tcl applications
that use \fBputs\fR to produce output.
.SH KEYWORDS
test, test harness, test suite
.\" Local Variables:
.\" mode: nroff
.\" End:







|
|

|


|


<
<
<
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128



.QW n ,
.QW o ,
and
.QW p
refer to tests that were run at the same test level as test level-1.1.
.PP
Implementation of output and error comparison in the test command
depends on usage of ::puts in your application code.  Output is
intercepted by redefining the ::puts command while the defined test
script is being run.  Errors thrown by C procedures or printed
directly from C applications will not be caught by the test command.
Therefore, usage of the \fB\-output\fR and \fB\-errorOutput\fR
options to \fBtest\fR is useful only for pure Tcl applications
that use \fB::puts\fR to produce output. 
.SH KEYWORDS
test, test harness, test suite



Deleted doc/timerate.n.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
'\"
'\" Copyright (c) 2005 Sergey Brester aka sebres.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH timerate n "" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
timerate \- Calibrated performance measurements of script execution time
.SH SYNOPSIS
\fBtimerate \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.sp
\fBtimerate \fR?\fB\-direct\fR? ?\fB\-overhead\fI double\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.sp
\fBtimerate \fR?\fB\-calibrate\fR? ?\fB\-direct\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.BE
.SH DESCRIPTION
.PP
The \fBtimerate\fR command does calibrated performance measurement of a Tcl
command or script, \fIscript\fR. The \fIscript\fR should be written so that it
can be executed multiple times during the performance measurement process.
Time is measured in elapsed time using the finest timer resolution as possible,
not CPU time; if \fIscript\fR interacts with the OS, the cost of that
interaction is included.
This command may be used to provide information as to how well a script or
Tcl command is performing, and can help determine bottlenecks and fine-tune
application performance.
.PP
The first and second form will evaluate \fIscript\fR until the interval
\fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second)
if \fItime\fR is not specified.
.sp
The parameter \fImax-count\fR could additionally impose a further restriction
by the maximal number of iterations to evaluate the script.
If \fImax-count\fR is specified, the evalution will stop either this count of
iterations is reached or the time is exceeded.
.sp
It will then return a canonical tcl-list of the form:
.PP
.CS
\fB0.095977 \(mcs/# 52095836 # 10419167 #/sec 5000.000 net-ms\fR
.CE
.PP
which indicates:
.IP \(bu 3
the average amount of time required per iteration, in microseconds ([\fBlindex\fR $result 0])
.IP \(bu 3
the count how many times it was executed ([\fBlindex\fR $result 2])
.IP \(bu 3
the estimated rate per second ([\fBlindex\fR $result 4])
.IP \(bu 3
the estimated real execution time without measurement overhead ([\fBlindex\fR $result 6])
.PP
The following options may be supplied to the \fBtimerate\fR command:
.TP
\fB\-calibrate\fR
.
To measure very fast scripts as exactly as possible, a calibration process
may be required.
The \fB\-calibrate\fR option is used to calibrate \fBtimerate\fR itself,
calculating the estimated overhead of the given script as the default overhead
for future invocations of the \fBtimerate\fR command. If the \fItime\fR
parameter is not specified, the calibrate procedure runs for up to 10 seconds.
.RS
.PP
Note that calibration is not thread safe in the current implementation.
.RE
.TP
\fB\-overhead \fIdouble\fR
.
The \fB\-overhead\fR parameter supplies an estimate (in microseconds) of the
measurement overhead of each iteration of the tested script. This quantity
will be subtracted from the measured time prior to reporting results. This can
be useful for removing the cost of interpreter state reset commands from the
script being measured.
.TP
\fB\-direct\fR
.
The \fB-direct\fR option causes direct execution of the supplied script,
without compilation, in a manner similar to the \fBtime\fR command. It can be
used to measure the cost of \fBTcl_EvalObjEx\fR, of the invocation of canonical
lists, and of the uncompiled versions of bytecoded commands.
.PP
As opposed to the \fBtime\fR commmand, which runs the tested script for a fixed
number of iterations, the timerate command runs it for a fixed time.
Additionally, the compiled variant of the script will be used during the entire
measurement, as if the script were part of a compiled procedure, if the \fB\-direct\fR
option is not specified. The fixed time period and possibility of compilation allow
for more precise results and prevent very long execution times by slow scripts, making
it practical for measuring scripts with highly uncertain execution times.
.SH EXAMPLES
Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including
operations on variable \fIi\fR) to count to ten:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}

\fI# measure\fR
\fBtimerate\fR { for {set i 0} {$i<10} {incr i} {} } 5000
.CE
.PP
Estimate how fast it takes for a simple Tcl \fBfor\fR loop, ignoring the
overhead of the management of the variable that controls the loop:
.PP
.CS
\fI# calibrate for overhead of variable operations\fR
set i 0; \fBtimerate\fR -calibrate {expr {$i<10}; incr i} 1000

\fI# measure\fR
\fBtimerate\fR {
    for {set i 0} {$i<10} {incr i} {}
} 5000
.CE
.PP
Estimate the speed of calculating the hour of the day using \fBclock format\fR only,
ignoring overhead of the portion of the script that prepares the time for it to
calculate:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}

\fI# estimate overhead\fR
set tm 0
set ovh [lindex [\fBtimerate\fR {
    incr tm [expr {24*60*60}]
}] 0]

\fI# measure using estimated overhead\fR
set tm 0
\fBtimerate\fR -overhead $ovh {
    clock format $tm -format %H
    incr tm [expr {24*60*60}]; # overhead for this is ignored
} 5000
.CE
.SH "SEE ALSO"
time(n)
.SH KEYWORDS
performance measurement, script, time
.\" Local Variables:
.\" mode: nroff
.\" End:
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































Changes to generic/regc_lex.c.

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#define	INCON(con)	(v->lexcon == (con))

/* construct pointer past end of chr array */
#define	ENDOF(array)	((array) + sizeof(array)/sizeof(chr))

/*
 - lexstart - set up lexical stuff, scan leading options
 ^ static void lexstart(struct vars *);
 */
static void
lexstart(
    struct vars *v)
{
    prefixes(v);		/* may turn on new type bits etc. */
    NOERR();







|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#define	INCON(con)	(v->lexcon == (con))

/* construct pointer past end of chr array */
#define	ENDOF(array)	((array) + sizeof(array)/sizeof(chr))

/*
 - lexstart - set up lexical stuff, scan leading options
 ^ static VOID lexstart(struct vars *);
 */
static void
lexstart(
    struct vars *v)
{
    prefixes(v);		/* may turn on new type bits etc. */
    NOERR();
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

    v->nexttype = EMPTY;	/* remember we were at the start */
    next(v);			/* set up the first token */
}

/*
 - prefixes - implement various special prefixes
 ^ static void prefixes(struct vars *);
 */
static void
prefixes(
    struct vars *v)
{
    /*
     * Literal string doesn't get any of this stuff.







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

    v->nexttype = EMPTY;	/* remember we were at the start */
    next(v);			/* set up the first token */
}

/*
 - prefixes - implement various special prefixes
 ^ static VOID prefixes(struct vars *);
 */
static void
prefixes(
    struct vars *v)
{
    /*
     * Literal string doesn't get any of this stuff.
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    }
}

/*
 - lexnest - "call a subroutine", interpolating string at the lexical level
 * Note, this is not a very general facility.  There are a number of
 * implicit assumptions about what sorts of strings can be subroutines.
 ^ static void lexnest(struct vars *, const chr *, const chr *);
 */
static void
lexnest(
    struct vars *v,
    const chr *beginp,		/* start of interpolation */
    const chr *endp)		/* one past end of interpolation */
{







|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    }
}

/*
 - lexnest - "call a subroutine", interpolating string at the lexical level
 * Note, this is not a very general facility.  There are a number of
 * implicit assumptions about what sorts of strings can be subroutines.
 ^ static VOID lexnest(struct vars *, const chr *, const chr *);
 */
static void
lexnest(
    struct vars *v,
    const chr *beginp,		/* start of interpolation */
    const chr *endp)		/* one past end of interpolation */
{
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    CHR('['), CHR(':'),
    CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
    CHR(':'), CHR(']')
};

#define PUNCT_CONN \
	CHR('_'), \
	0x203F /* UNDERTIE */, \
	0x2040 /* CHARACTER TIE */,\
	0x2054 /* INVERTED UNDERTIE */,\
	0xFE33 /* PRESENTATION FORM FOR VERTICAL LOW LINE */, \
	0xFE34 /* PRESENTATION FORM FOR VERTICAL WAVY LOW LINE */, \
	0xFE4D /* DASHED LOW LINE */, \
	0xFE4E /* CENTRELINE LOW LINE */, \
	0xFE4F /* WAVY LOW LINE */, \
	0xFF3F /* FULLWIDTH LOW LINE */

static const chr backw[] = {	/* \w */
    CHR('['), CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
};
static const chr backW[] = {	/* \W */
    CHR('['), CHR('^'), CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
};
static const chr brbackw[] = {	/* \w within brackets */
    CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN
};

/*
 - lexword - interpolate a bracket expression for word characters
 * Possibly ought to inquire whether there is a "word" character class.
 ^ static void lexword(struct vars *);
 */
static void
lexword(
    struct vars *v)
{
    lexnest(v, backw, ENDOF(backw));
}







|


|
|
|
|
|
|




















|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    CHR('['), CHR(':'),
    CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
    CHR(':'), CHR(']')
};

#define PUNCT_CONN \
	CHR('_'), \
	0x203f /* UNDERTIE */, \
	0x2040 /* CHARACTER TIE */,\
	0x2054 /* INVERTED UNDERTIE */,\
	0xfe33 /* PRESENTATION FORM FOR VERTICAL LOW LINE */, \
	0xfe34 /* PRESENTATION FORM FOR VERTICAL WAVY LOW LINE */, \
	0xfe4d /* DASHED LOW LINE */, \
	0xfe4e /* CENTRELINE LOW LINE */, \
	0xfe4f /* WAVY LOW LINE */, \
	0xff3f /* FULLWIDTH LOW LINE */

static const chr backw[] = {	/* \w */
    CHR('['), CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
};
static const chr backW[] = {	/* \W */
    CHR('['), CHR('^'), CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN, CHR(']')
};
static const chr brbackw[] = {	/* \w within brackets */
    CHR('['), CHR(':'),
    CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
    CHR(':'), CHR(']'), PUNCT_CONN
};

/*
 - lexword - interpolate a bracket expression for word characters
 * Possibly ought to inquire whether there is a "word" character class.
 ^ static VOID lexword(struct vars *);
 */
static void
lexword(
    struct vars *v)
{
    lexnest(v, backw, ENDOF(backw));
}
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
		FAILW(REG_BADBR);
	    }
	    break;
	case CHR('\\'):		/* BRE bound ends with \} */
	    if (INCON(L_BBND) && NEXT1('}')) {
		v->now++;
		INTOCON(L_BRE);
		RETV('}', 1);
	    } else {
		FAILW(REG_BADBR);
	    }
	    break;
	default:
	    FAILW(REG_BADBR);
	    break;







|







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
		FAILW(REG_BADBR);
	    }
	    break;
	case CHR('\\'):		/* BRE bound ends with \} */
	    if (INCON(L_BBND) && NEXT1('}')) {
		v->now++;
		INTOCON(L_BRE);
		RET('}');
	    } else {
		FAILW(REG_BADBR);
	    }
	    break;
	default:
	    FAILW(REG_BADBR);
	    break;
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
 ^ static int lexescape(struct vars *);
 */
static int			/* not actually used, but convenient for RETV */
lexescape(
    struct vars *v)
{
    chr c;
    int i;
    static const chr alert[] = {
	CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
    };
    static const chr esc[] = {
	CHR('E'), CHR('S'), CHR('C')
    };
    const chr *save;







<







751
752
753
754
755
756
757

758
759
760
761
762
763
764
 ^ static int lexescape(struct vars *);
 */
static int			/* not actually used, but convenient for RETV */
lexescape(
    struct vars *v)
{
    chr c;

    static const chr alert[] = {
	CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
    };
    static const chr esc[] = {
	CHR('E'), CHR('S'), CHR('C')
    };
    const chr *save;
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
	NOTE(REG_ULOCALE);
	RETV(CCLASS, 'S');
	break;
    case CHR('t'):
	RETV(PLAIN, CHR('\t'));
	break;
    case CHR('u'):
	c = (uchr) lexdigits(v, 16, 4, 4);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
	}
	RETV(PLAIN, c);
	break;
    case CHR('U'):
	i = lexdigits(v, 16, 8, 8);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
	}
#if CHRBITS > 16
	if ((unsigned)i > 0x10FFFF) {
	    i = 0xFFFD;
	}
#else
	if ((unsigned)i & ~0xFFFF) {
	    i = 0xFFFD;
	}
#endif
	RETV(PLAIN, (uchr)i);
	break;
    case CHR('v'):
	RETV(PLAIN, CHR('\v'));
	break;
    case CHR('w'):
	NOTE(REG_ULOCALE);
	RETV(CCLASS, 'w');







|






|



<
<
<
<
<
<
<
<
<
|







827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844









845
846
847
848
849
850
851
852
	NOTE(REG_ULOCALE);
	RETV(CCLASS, 'S');
	break;
    case CHR('t'):
	RETV(PLAIN, CHR('\t'));
	break;
    case CHR('u'):
	c = lexdigits(v, 16, 4, 4);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
	}
	RETV(PLAIN, c);
	break;
    case CHR('U'):
	c = lexdigits(v, 16, 8, 8);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
	}









	RETV(PLAIN, c);
	break;
    case CHR('v'):
	RETV(PLAIN, CHR('\v'));
	break;
    case CHR('w'):
	NOTE(REG_ULOCALE);
	RETV(CCLASS, 'w');
905
906
907
908
909
910
911
912


913
914
915
916
917
918
919

	/*
	 * Oops, doesn't look like it's a backref after all...
	 */

	v->now = save;

	/* FALLTHRU */



    case CHR('0'):
	NOTE(REG_UUNPORT);
	v->now--;		/* put first digit back */
	c = lexdigits(v, 8, 1, 3);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);







|
>
>







895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911

	/*
	 * Oops, doesn't look like it's a backref after all...
	 */

	v->now = save;

	/*
	 * And fall through into octal number.
	 */

    case CHR('0'):
	NOTE(REG_UUNPORT);
	v->now--;		/* put first digit back */
	c = lexdigits(v, 8, 1, 3);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
    chr c = (chr)pc;

    switch (c) {
    case CHR('*'):
	if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) {
	    RETV(PLAIN, c);
	}
	RETV('*', 1);
	break;
    case CHR('['):
	if (HAVE(6) &&	*(v->now+0) == CHR('[') &&
		*(v->now+1) == CHR(':') &&
		(*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) &&
		*(v->now+3) == CHR(':') &&
		*(v->now+4) == CHR(']') &&







|







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
    chr c = (chr)pc;

    switch (c) {
    case CHR('*'):
	if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) {
	    RETV(PLAIN, c);
	}
	RET('*');
	break;
    case CHR('['):
	if (HAVE(6) &&	*(v->now+0) == CHR('[') &&
		*(v->now+1) == CHR(':') &&
		(*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) &&
		*(v->now+3) == CHR(':') &&
		*(v->now+4) == CHR(']') &&

Changes to generic/regc_locale.c.

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

273
274
275
276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
 */

/*
 * Unicode: alphabetic characters.
 */

static const crange alphaRangeTable[] = {
    {0x41, 0x5A}, {0x61, 0x7A}, {0xC0, 0xD6}, {0xD8, 0xF6},
    {0xF8, 0x2C1}, {0x2C6, 0x2D1}, {0x2E0, 0x2E4}, {0x370, 0x374},
    {0x37A, 0x37D}, {0x388, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x3F5},
    {0x3F7, 0x481}, {0x48A, 0x52F}, {0x531, 0x556}, {0x560, 0x588},
    {0x5D0, 0x5EA}, {0x5EF, 0x5F2}, {0x620, 0x64A}, {0x671, 0x6D3},
    {0x6FA, 0x6FC}, {0x712, 0x72F}, {0x74D, 0x7A5}, {0x7CA, 0x7EA},
    {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86A}, {0x870, 0x887},
    {0x889, 0x88E}, {0x8A0, 0x8C9}, {0x904, 0x939}, {0x958, 0x961},
    {0x971, 0x980}, {0x985, 0x98C}, {0x993, 0x9A8}, {0x9AA, 0x9B0},
    {0x9B6, 0x9B9}, {0x9DF, 0x9E1}, {0xA05, 0xA0A}, {0xA13, 0xA28},
    {0xA2A, 0xA30}, {0xA59, 0xA5C}, {0xA72, 0xA74}, {0xA85, 0xA8D},
    {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9},
    {0xB05, 0xB0C}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39},
    {0xB5F, 0xB61}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95},
    {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xC05, 0xC0C}, {0xC0E, 0xC10},
    {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC58, 0xC5A}, {0xC85, 0xC8C},
    {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9},
    {0xD04, 0xD0C}, {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD54, 0xD56},
    {0xD5F, 0xD61}, {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1},
    {0xDB3, 0xDBB}, {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE40, 0xE46},
    {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA7, 0xEB0}, {0xEC0, 0xEC4},
    {0xEDC, 0xEDF}, {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C},
    {0x1000, 0x102A}, {0x1050, 0x1055}, {0x105A, 0x105D}, {0x106E, 0x1070},
    {0x1075, 0x1081}, {0x10A0, 0x10C5}, {0x10D0, 0x10FA}, {0x10FC, 0x1248},
    {0x124A, 0x124D}, {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288},
    {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
    {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315},
    {0x1318, 0x135A}, {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
    {0x1401, 0x166C}, {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA},
    {0x16F1, 0x16F8}, {0x1700, 0x1711}, {0x171F, 0x1731}, {0x1740, 0x1751},
    {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1780, 0x17B3}, {0x1820, 0x1878},
    {0x1880, 0x1884}, {0x1887, 0x18A8}, {0x18B0, 0x18F5}, {0x1900, 0x191E},

    {0x1950, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
    {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4C},
    {0x1B83, 0x1BA0}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F},
    {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF},
    {0x1CE9, 0x1CEC}, {0x1CEE, 0x1CF3}, {0x1D00, 0x1DBF}, {0x1E00, 0x1F15},
    {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57},
    {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC}, {0x1FC2, 0x1FC4},
    {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC},
    {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x2090, 0x209C}, {0x210A, 0x2113},
    {0x2119, 0x211D}, {0x212A, 0x212D}, {0x212F, 0x2139}, {0x213C, 0x213F},
    {0x2145, 0x2149}, {0x2C00, 0x2CE4}, {0x2CEB, 0x2CEE}, {0x2D00, 0x2D25},

    {0x2D30, 0x2D67}, {0x2D80, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
    {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE},
    {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x3031, 0x3035}, {0x3041, 0x3096},
    {0x309D, 0x309F}, {0x30A1, 0x30FA}, {0x30FC, 0x30FF}, {0x3105, 0x312F},
    {0x3131, 0x318E}, {0x31A0, 0x31BF}, {0x31F0, 0x31FF}, {0x3400, 0x4DBF},
    {0x4E00, 0xA48C}, {0xA4D0, 0xA4FD}, {0xA500, 0xA60C}, {0xA610, 0xA61F},
    {0xA640, 0xA66E}, {0xA67F, 0xA69D}, {0xA6A0, 0xA6E5}, {0xA717, 0xA71F},
    {0xA722, 0xA788}, {0xA78B, 0xA7CA}, {0xA7D5, 0xA7D9}, {0xA7F2, 0xA801},
    {0xA803, 0xA805}, {0xA807, 0xA80A}, {0xA80C, 0xA822}, {0xA840, 0xA873},
    {0xA882, 0xA8B3}, {0xA8F2, 0xA8F7}, {0xA90A, 0xA925}, {0xA930, 0xA946},
    {0xA960, 0xA97C}, {0xA984, 0xA9B2}, {0xA9E0, 0xA9E4}, {0xA9E6, 0xA9EF},
    {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA40, 0xAA42}, {0xAA44, 0xAA4B},
    {0xAA60, 0xAA76}, {0xAA7E, 0xAAAF}, {0xAAB9, 0xAABD}, {0xAADB, 0xAADD},
    {0xAAE0, 0xAAEA}, {0xAAF2, 0xAAF4}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
    {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB5A},
    {0xAB5C, 0xAB69}, {0xAB70, 0xABE2}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6},
    {0xD7CB, 0xD7FB}, {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06},
    {0xFB13, 0xFB17}, {0xFB1F, 0xFB28}, {0xFB2A, 0xFB36}, {0xFB38, 0xFB3C},
    {0xFB46, 0xFBB1}, {0xFBD3, 0xFD3D}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7},
    {0xFDF0, 0xFDFB}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF21, 0xFF3A},
    {0xFF41, 0xFF5A}, {0xFF66, 0xFFBE}, {0xFFC2, 0xFFC7}, {0xFFCA, 0xFFCF},
    {0xFFD2, 0xFFD7}, {0xFFDA, 0xFFDC}
#if CHRBITS > 16
    ,{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003F, 0x1004D},
    {0x10050, 0x1005D}, {0x10080, 0x100FA}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
    {0x10300, 0x1031F}, {0x1032D, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
    {0x10380, 0x1039D}, {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x10400, 0x1049D},
    {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
    {0x10570, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592}, {0x10597, 0x105A1},
    {0x105A3, 0x105B1}, {0x105B3, 0x105B9}, {0x10600, 0x10736}, {0x10740, 0x10755},
    {0x10760, 0x10767}, {0x10780, 0x10785}, {0x10787, 0x107B0}, {0x107B2, 0x107BA},
    {0x10800, 0x10805}, {0x1080A, 0x10835}, {0x1083F, 0x10855}, {0x10860, 0x10876},
    {0x10880, 0x1089E}, {0x108E0, 0x108F2}, {0x10900, 0x10915}, {0x10920, 0x10939},
    {0x10980, 0x109B7}, {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
    {0x10A60, 0x10A7C}, {0x10A80, 0x10A9C}, {0x10AC0, 0x10AC7}, {0x10AC9, 0x10AE4},
    {0x10B00, 0x10B35}, {0x10B40, 0x10B55}, {0x10B60, 0x10B72}, {0x10B80, 0x10B91},
    {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, {0x10D00, 0x10D23},
    {0x10E80, 0x10EA9}, {0x10F00, 0x10F1C}, {0x10F30, 0x10F45}, {0x10F70, 0x10F81},
    {0x10FB0, 0x10FC4}, {0x10FE0, 0x10FF6}, {0x11003, 0x11037}, {0x11083, 0x110AF},
    {0x110D0, 0x110E8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111B2},
    {0x111C1, 0x111C4}, {0x11200, 0x11211}, {0x11213, 0x1122B}, {0x11280, 0x11286},
    {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112B0, 0x112DE},
    {0x11305, 0x1130C}, {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11335, 0x11339},
    {0x1135D, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144A}, {0x1145F, 0x11461},
    {0x11480, 0x114AF}, {0x11580, 0x115AE}, {0x115D8, 0x115DB}, {0x11600, 0x1162F},
    {0x11680, 0x116AA}, {0x11700, 0x1171A}, {0x11740, 0x11746}, {0x11800, 0x1182B},
    {0x118A0, 0x118DF}, {0x118FF, 0x11906}, {0x1190C, 0x11913}, {0x11918, 0x1192F},
    {0x119A0, 0x119A7}, {0x119AA, 0x119D0}, {0x11A0B, 0x11A32}, {0x11A5C, 0x11A89},
    {0x11AB0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C72, 0x11C8F},
    {0x11D00, 0x11D06}, {0x11D0B, 0x11D30}, {0x11D60, 0x11D65}, {0x11D6A, 0x11D89},
    {0x11EE0, 0x11EF2}, {0x11F04, 0x11F10}, {0x11F12, 0x11F33}, {0x12000, 0x12399},
    {0x12480, 0x12543}, {0x12F90, 0x12FF0}, {0x13000, 0x1342F}, {0x13441, 0x13446},
    {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A70, 0x16ABE},
    {0x16AD0, 0x16AED}, {0x16B00, 0x16B2F}, {0x16B40, 0x16B43}, {0x16B63, 0x16B77},
    {0x16B7D, 0x16B8F}, {0x16E40, 0x16E7F}, {0x16F00, 0x16F4A}, {0x16F93, 0x16F9F},
    {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08}, {0x1AFF0, 0x1AFF3},

    {0x1AFF5, 0x1AFFB}, {0x1B000, 0x1B122}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167},
    {0x1B170, 0x1B2FB}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88},
    {0x1BC90, 0x1BC99}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D4A9, 0x1D4AC},
    {0x1D4AE, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A},
    {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
    {0x1D540, 0x1D544}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0},
    {0x1D6C2, 0x1D6DA}, {0x1D6DC, 0x1D6FA}, {0x1D6FC, 0x1D714}, {0x1D716, 0x1D734},
    {0x1D736, 0x1D74E}, {0x1D750, 0x1D76E}, {0x1D770, 0x1D788}, {0x1D78A, 0x1D7A8},
    {0x1D7AA, 0x1D7C2}, {0x1D7C4, 0x1D7CB}, {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A},
    {0x1E030, 0x1E06D}, {0x1E100, 0x1E12C}, {0x1E137, 0x1E13D}, {0x1E290, 0x1E2AD},
    {0x1E2C0, 0x1E2EB}, {0x1E4D0, 0x1E4EB}, {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB},
    {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E900, 0x1E943}, {0x1EE00, 0x1EE03},
    {0x1EE05, 0x1EE1F}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F},
    {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C},
    {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9},
    {0x1EEAB, 0x1EEBB}, {0x20000, 0x2A6DF}, {0x2A700, 0x2B739}, {0x2B740, 0x2B81D},
    {0x2B820, 0x2CEA1}, {0x2CEB0, 0x2EBE0}, {0x2F800, 0x2FA1D}, {0x30000, 0x3134A},
    {0x31350, 0x323AF}
#endif
};

#define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))

static const chr alphaCharTable[] = {
    0xAA, 0xB5, 0xBA, 0x2EC, 0x2EE, 0x376, 0x377, 0x37F, 0x386,
    0x38C, 0x559, 0x66E, 0x66F, 0x6D5, 0x6E5, 0x6E6, 0x6EE, 0x6EF,
    0x6FF, 0x710, 0x7B1, 0x7F4, 0x7F5, 0x7FA, 0x81A, 0x824, 0x828,
    0x93D, 0x950, 0x98F, 0x990, 0x9B2, 0x9BD, 0x9CE, 0x9DC, 0x9DD,
    0x9F0, 0x9F1, 0x9FC, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36,
    0xA38, 0xA39, 0xA5E, 0xAB2, 0xAB3, 0xABD, 0xAD0, 0xAE0, 0xAE1,
    0xAF9, 0xB0F, 0xB10, 0xB32, 0xB33, 0xB3D, 0xB5C, 0xB5D, 0xB71,
    0xB83, 0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0,
    0xC3D, 0xC5D, 0xC60, 0xC61, 0xC80, 0xCBD, 0xCDD, 0xCDE, 0xCE0,
    0xCE1, 0xCF1, 0xCF2, 0xD3D, 0xD4E, 0xDBD, 0xE32, 0xE33, 0xE81,
    0xE82, 0xE84, 0xEA5, 0xEB2, 0xEB3, 0xEBD, 0xEC6, 0xF00, 0x103F,
    0x1061, 0x1065, 0x1066, 0x108E, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x17D7,
    0x17DC, 0x18AA, 0x1AA7, 0x1BAE, 0x1BAF, 0x1CF5, 0x1CF6, 0x1CFA, 0x1F59,

    0x1F5B, 0x1F5D, 0x1FBE, 0x2071, 0x207F, 0x2102, 0x2107, 0x2115, 0x2124,
    0x2126, 0x2128, 0x214E, 0x2183, 0x2184, 0x2CF2, 0x2CF3, 0x2D27, 0x2D2D,
    0x2D6F, 0x2E2F, 0x3005, 0x3006, 0x303B, 0x303C, 0xA62A, 0xA62B, 0xA7D0,
    0xA7D1, 0xA7D3, 0xA8FB, 0xA8FD, 0xA8FE, 0xA9CF, 0xAA7A, 0xAAB1, 0xAAB5,
    0xAAB6, 0xAAC0, 0xAAC2, 0xFB1D, 0xFB3E, 0xFB40, 0xFB41, 0xFB43, 0xFB44

#if CHRBITS > 16
    ,0x1003C, 0x1003D, 0x10594, 0x10595, 0x105BB, 0x105BC, 0x10808, 0x10837, 0x10838,
    0x1083C, 0x108F4, 0x108F5, 0x109BE, 0x109BF, 0x10A00, 0x10EB0, 0x10EB1, 0x10F27,
    0x11071, 0x11072, 0x11075, 0x11144, 0x11147, 0x11176, 0x111DA, 0x111DC, 0x1123F,
    0x11240, 0x11288, 0x1130F, 0x11310, 0x11332, 0x11333, 0x1133D, 0x11350, 0x114C4,
    0x114C5, 0x114C7, 0x11644, 0x116B8, 0x11909, 0x11915, 0x11916, 0x1193F, 0x11941,
    0x119E1, 0x119E3, 0x11A00, 0x11A3A, 0x11A50, 0x11A9D, 0x11C40, 0x11D08, 0x11D09,
    0x11D46, 0x11D67, 0x11D68, 0x11D98, 0x11F02, 0x11FB0, 0x16F50, 0x16FE0, 0x16FE1,
    0x16FE3, 0x1AFFD, 0x1AFFE, 0x1B132, 0x1B155, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5,
    0x1D4A6, 0x1D4BB, 0x1D546, 0x1E14E, 0x1E7ED, 0x1E7EE, 0x1E94B, 0x1EE21, 0x1EE22,
    0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51,
    0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62,
    0x1EE64, 0x1EE7E
#endif
};

#define NUM_ALPHA_CHAR (sizeof(alphaCharTable)/sizeof(chr))

/*
 * Unicode: control characters.
 */

static const crange controlRangeTable[] = {
    {0x0, 0x1F}, {0x7F, 0x9F}, {0x600, 0x605}, {0x200B, 0x200F},
    {0x202A, 0x202E}, {0x2060, 0x2064}, {0x2066, 0x206F}, {0xE000, 0xF8FF},
    {0xFFF9, 0xFFFB}
#if CHRBITS > 16
    ,{0x13430, 0x1343F}, {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0020, 0xE007F},
    {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
#endif
};

#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))

static const chr controlCharTable[] = {
    0xAD, 0x61C, 0x6DD, 0x70F, 0x890, 0x891, 0x8E2, 0x180E, 0xFEFF
#if CHRBITS > 16
    ,0x110BD, 0x110CD, 0xE0001
#endif
};

#define NUM_CONTROL_CHAR (sizeof(controlCharTable)/sizeof(chr))

/*
 * Unicode: decimal digit characters.
 */

static const crange digitRangeTable[] = {
    {0x30, 0x39}, {0x660, 0x669}, {0x6F0, 0x6F9}, {0x7C0, 0x7C9},
    {0x966, 0x96F}, {0x9E6, 0x9EF}, {0xA66, 0xA6F}, {0xAE6, 0xAEF},
    {0xB66, 0xB6F}, {0xBE6, 0xBEF}, {0xC66, 0xC6F}, {0xCE6, 0xCEF},
    {0xD66, 0xD6F}, {0xDE6, 0xDEF}, {0xE50, 0xE59}, {0xED0, 0xED9},
    {0xF20, 0xF29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x17E0, 0x17E9},
    {0x1810, 0x1819}, {0x1946, 0x194F}, {0x19D0, 0x19D9}, {0x1A80, 0x1A89},
    {0x1A90, 0x1A99}, {0x1B50, 0x1B59}, {0x1BB0, 0x1BB9}, {0x1C40, 0x1C49},
    {0x1C50, 0x1C59}, {0xA620, 0xA629}, {0xA8D0, 0xA8D9}, {0xA900, 0xA909},
    {0xA9D0, 0xA9D9}, {0xA9F0, 0xA9F9}, {0xAA50, 0xAA59}, {0xABF0, 0xABF9},
    {0xFF10, 0xFF19}
#if CHRBITS > 16
    ,{0x104A0, 0x104A9}, {0x10D30, 0x10D39}, {0x11066, 0x1106F}, {0x110F0, 0x110F9},
    {0x11136, 0x1113F}, {0x111D0, 0x111D9}, {0x112F0, 0x112F9}, {0x11450, 0x11459},
    {0x114D0, 0x114D9}, {0x11650, 0x11659}, {0x116C0, 0x116C9}, {0x11730, 0x11739},
    {0x118E0, 0x118E9}, {0x11950, 0x11959}, {0x11C50, 0x11C59}, {0x11D50, 0x11D59},
    {0x11DA0, 0x11DA9}, {0x11F50, 0x11F59}, {0x16A60, 0x16A69}, {0x16AC0, 0x16AC9},
    {0x16B50, 0x16B59}, {0x1D7CE, 0x1D7FF}, {0x1E140, 0x1E149}, {0x1E2F0, 0x1E2F9},
    {0x1E4F0, 0x1E4F9}, {0x1E950, 0x1E959}, {0x1FBF0, 0x1FBF9}
#endif
};

#define NUM_DIGIT_RANGE (sizeof(digitRangeTable)/sizeof(crange))

/*
 * no singletons of digit characters.
 */

/*
 * Unicode: punctuation characters.
 */

static const crange punctRangeTable[] = {
    {0x21, 0x23}, {0x25, 0x2A}, {0x2C, 0x2F}, {0x5B, 0x5D},
    {0x55A, 0x55F}, {0x61D, 0x61F}, {0x66A, 0x66D}, {0x700, 0x70D},
    {0x7F7, 0x7F9}, {0x830, 0x83E}, {0xF04, 0xF12}, {0xF3A, 0xF3D},
    {0xFD0, 0xFD4}, {0x104A, 0x104F}, {0x1360, 0x1368}, {0x16EB, 0x16ED},
    {0x17D4, 0x17D6}, {0x17D8, 0x17DA}, {0x1800, 0x180A}, {0x1AA0, 0x1AA6},
    {0x1AA8, 0x1AAD}, {0x1B5A, 0x1B60}, {0x1BFC, 0x1BFF}, {0x1C3B, 0x1C3F},
    {0x1CC0, 0x1CC7}, {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051},
    {0x2053, 0x205E}, {0x2308, 0x230B}, {0x2768, 0x2775}, {0x27E6, 0x27EF},
    {0x2983, 0x2998}, {0x29D8, 0x29DB}, {0x2CF9, 0x2CFC}, {0x2E00, 0x2E2E},
    {0x2E30, 0x2E4F}, {0x2E52, 0x2E5D}, {0x3001, 0x3003}, {0x3008, 0x3011},
    {0x3014, 0x301F}, {0xA60D, 0xA60F}, {0xA6F2, 0xA6F7}, {0xA874, 0xA877},
    {0xA8F8, 0xA8FA}, {0xA9C1, 0xA9CD}, {0xAA5C, 0xAA5F}, {0xFE10, 0xFE19},
    {0xFE30, 0xFE52}, {0xFE54, 0xFE61}, {0xFF01, 0xFF03}, {0xFF05, 0xFF0A},
    {0xFF0C, 0xFF0F}, {0xFF3B, 0xFF3D}, {0xFF5F, 0xFF65}
#if CHRBITS > 16
    ,{0x10100, 0x10102}, {0x10A50, 0x10A58}, {0x10AF0, 0x10AF6}, {0x10B39, 0x10B3F},
    {0x10B99, 0x10B9C}, {0x10F55, 0x10F59}, {0x10F86, 0x10F89}, {0x11047, 0x1104D},
    {0x110BE, 0x110C1}, {0x11140, 0x11143}, {0x111C5, 0x111C8}, {0x111DD, 0x111DF},
    {0x11238, 0x1123D}, {0x1144B, 0x1144F}, {0x115C1, 0x115D7}, {0x11641, 0x11643},
    {0x11660, 0x1166C}, {0x1173C, 0x1173E}, {0x11944, 0x11946}, {0x11A3F, 0x11A46},
    {0x11A9A, 0x11A9C}, {0x11A9E, 0x11AA2}, {0x11B00, 0x11B09}, {0x11C41, 0x11C45},
    {0x11F43, 0x11F4F}, {0x12470, 0x12474}, {0x16B37, 0x16B3B}, {0x16E97, 0x16E9A},
    {0x1DA87, 0x1DA8B}
#endif
};

#define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange))

static const chr punctCharTable[] = {
    0x3A, 0x3B, 0x3F, 0x40, 0x5F, 0x7B, 0x7D, 0xA1, 0xA7,
    0xAB, 0xB6, 0xB7, 0xBB, 0xBF, 0x37E, 0x387, 0x589, 0x58A,
    0x5BE, 0x5C0, 0x5C3, 0x5C6, 0x5F3, 0x5F4, 0x609, 0x60A, 0x60C,
    0x60D, 0x61B, 0x6D4, 0x85E, 0x964, 0x965, 0x970, 0x9FD, 0xA76,
    0xAF0, 0xC77, 0xC84, 0xDF4, 0xE4F, 0xE5A, 0xE5B, 0xF14, 0xF85,
    0xFD9, 0xFDA, 0x10FB, 0x1400, 0x166E, 0x169B, 0x169C, 0x1735, 0x1736,
    0x1944, 0x1945, 0x1A1E, 0x1A1F, 0x1B7D, 0x1B7E, 0x1C7E, 0x1C7F, 0x1CD3,
    0x207D, 0x207E, 0x208D, 0x208E, 0x2329, 0x232A, 0x27C5, 0x27C6, 0x29FC,
    0x29FD, 0x2CFE, 0x2CFF, 0x2D70, 0x3030, 0x303D, 0x30A0, 0x30FB, 0xA4FE,
    0xA4FF, 0xA673, 0xA67E, 0xA8CE, 0xA8CF, 0xA8FC, 0xA92E, 0xA92F, 0xA95F,
    0xA9DE, 0xA9DF, 0xAADE, 0xAADF, 0xAAF0, 0xAAF1, 0xABEB, 0xFD3E, 0xFD3F,
    0xFE63, 0xFE68, 0xFE6A, 0xFE6B, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF20, 0xFF3F,
    0xFF5B, 0xFF5D
#if CHRBITS > 16
    ,0x1039F, 0x103D0, 0x1056F, 0x10857, 0x1091F, 0x1093F, 0x10A7F, 0x10EAD, 0x110BB,
    0x110BC, 0x11174, 0x11175, 0x111CD, 0x111DB, 0x112A9, 0x1145A, 0x1145B, 0x1145D,
    0x114C6, 0x116B9, 0x1183B, 0x119E2, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF,
    0x12FF1, 0x12FF2, 0x16A6E, 0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E95E,
    0x1E95F
#endif
};

#define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr))

/*
 * Unicode: white space characters.
 */

static const crange spaceRangeTable[] = {
    {0x9, 0xD}, {0x2000, 0x200B}
};

#define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange))

static const chr spaceCharTable[] = {
    0x20, 0xA0, 0x1680, 0x180E, 0x2028, 0x2029, 0x202F, 0x205F,
    0x2060, 0x3000, 0xFEFF
};

#define NUM_SPACE_CHAR (sizeof(spaceCharTable)/sizeof(chr))

/*
 * Unicode: lowercase characters.
 */

static const crange lowerRangeTable[] = {
    {0x61, 0x7A}, {0xDF, 0xF6}, {0xF8, 0xFF}, {0x17E, 0x180},
    {0x199, 0x19B}, {0x1BD, 0x1BF}, {0x233, 0x239}, {0x24F, 0x293},
    {0x295, 0x2AF}, {0x37B, 0x37D}, {0x3AC, 0x3CE}, {0x3D5, 0x3D7},
    {0x3EF, 0x3F3}, {0x430, 0x45F}, {0x560, 0x588}, {0x10D0, 0x10FA},
    {0x10FD, 0x10FF}, {0x13F8, 0x13FD}, {0x1C80, 0x1C88}, {0x1D00, 0x1D2B},
    {0x1D6B, 0x1D77}, {0x1D79, 0x1D9A}, {0x1E95, 0x1E9D}, {0x1EFF, 0x1F07},
    {0x1F10, 0x1F15}, {0x1F20, 0x1F27}, {0x1F30, 0x1F37}, {0x1F40, 0x1F45},
    {0x1F50, 0x1F57}, {0x1F60, 0x1F67}, {0x1F70, 0x1F7D}, {0x1F80, 0x1F87},
    {0x1F90, 0x1F97}, {0x1FA0, 0x1FA7}, {0x1FB0, 0x1FB4}, {0x1FC2, 0x1FC4},
    {0x1FD0, 0x1FD3}, {0x1FE0, 0x1FE7}, {0x1FF2, 0x1FF4}, {0x2146, 0x2149},
    {0x2C30, 0x2C5F}, {0x2C76, 0x2C7B}, {0x2D00, 0x2D25}, {0xA72F, 0xA731},
    {0xA771, 0xA778}, {0xA793, 0xA795}, {0xAB30, 0xAB5A}, {0xAB60, 0xAB68},
    {0xAB70, 0xABBF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFF41, 0xFF5A}
#if CHRBITS > 16
    ,{0x10428, 0x1044F}, {0x104D8, 0x104FB}, {0x10597, 0x105A1}, {0x105A3, 0x105B1},
    {0x105B3, 0x105B9}, {0x10CC0, 0x10CF2}, {0x118C0, 0x118DF}, {0x16E60, 0x16E7F},
    {0x1D41A, 0x1D433}, {0x1D44E, 0x1D454}, {0x1D456, 0x1D467}, {0x1D482, 0x1D49B},
    {0x1D4B6, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D4CF}, {0x1D4EA, 0x1D503},
    {0x1D51E, 0x1D537}, {0x1D552, 0x1D56B}, {0x1D586, 0x1D59F}, {0x1D5BA, 0x1D5D3},
    {0x1D5EE, 0x1D607}, {0x1D622, 0x1D63B}, {0x1D656, 0x1D66F}, {0x1D68A, 0x1D6A5},
    {0x1D6C2, 0x1D6DA}, {0x1D6DC, 0x1D6E1}, {0x1D6FC, 0x1D714}, {0x1D716, 0x1D71B},
    {0x1D736, 0x1D74E}, {0x1D750, 0x1D755}, {0x1D770, 0x1D788}, {0x1D78A, 0x1D78F},
    {0x1D7AA, 0x1D7C2}, {0x1D7C4, 0x1D7C9}, {0x1DF00, 0x1DF09}, {0x1DF0B, 0x1DF1E},
    {0x1DF25, 0x1DF2A}, {0x1E922, 0x1E943}
#endif
};

#define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange))

static const chr lowerCharTable[] = {
    0xB5, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F,
    0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121,
    0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133,
    0x135, 0x137, 0x138, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144,
    0x146, 0x148, 0x149, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155,
    0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167,
    0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A,
    0x17C, 0x183, 0x185, 0x188, 0x18C, 0x18D, 0x192, 0x195, 0x19E,
    0x1A1, 0x1A3, 0x1A5, 0x1A8, 0x1AA, 0x1AB, 0x1AD, 0x1B0, 0x1B4,
    0x1B6, 0x1B9, 0x1BA, 0x1C6, 0x1C9, 0x1CC, 0x1CE, 0x1D0, 0x1D2,
    0x1D4, 0x1D6, 0x1D8, 0x1DA, 0x1DC, 0x1DD, 0x1DF, 0x1E1, 0x1E3,
    0x1E5, 0x1E7, 0x1E9, 0x1EB, 0x1ED, 0x1EF, 0x1F0, 0x1F3, 0x1F5,
    0x1F9, 0x1FB, 0x1FD, 0x1FF, 0x201, 0x203, 0x205, 0x207, 0x209,
    0x20B, 0x20D, 0x20F, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21B,
    0x21D, 0x21F, 0x221, 0x223, 0x225, 0x227, 0x229, 0x22B, 0x22D,
    0x22F, 0x231, 0x23C, 0x23F, 0x240, 0x242, 0x247, 0x249, 0x24B,
    0x24D, 0x371, 0x373, 0x377, 0x390, 0x3D0, 0x3D1, 0x3D9, 0x3DB,
    0x3DD, 0x3DF, 0x3E1, 0x3E3, 0x3E5, 0x3E7, 0x3E9, 0x3EB, 0x3ED,
    0x3F5, 0x3F8, 0x3FB, 0x3FC, 0x461, 0x463, 0x465, 0x467, 0x469,
    0x46B, 0x46D, 0x46F, 0x471, 0x473, 0x475, 0x477, 0x479, 0x47B,
    0x47D, 0x47F, 0x481, 0x48B, 0x48D, 0x48F, 0x491, 0x493, 0x495,
    0x497, 0x499, 0x49B, 0x49D, 0x49F, 0x4A1, 0x4A3, 0x4A5, 0x4A7,
    0x4A9, 0x4AB, 0x4AD, 0x4AF, 0x4B1, 0x4B3, 0x4B5, 0x4B7, 0x4B9,
    0x4BB, 0x4BD, 0x4BF, 0x4C2, 0x4C4, 0x4C6, 0x4C8, 0x4CA, 0x4CC,
    0x4CE, 0x4CF, 0x4D1, 0x4D3, 0x4D5, 0x4D7, 0x4D9, 0x4DB, 0x4DD,
    0x4DF, 0x4E1, 0x4E3, 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF,
    0x4F1, 0x4F3, 0x4F5, 0x4F7, 0x4F9, 0x4FB, 0x4FD, 0x4FF, 0x501,
    0x503, 0x505, 0x507, 0x509, 0x50B, 0x50D, 0x50F, 0x511, 0x513,
    0x515, 0x517, 0x519, 0x51B, 0x51D, 0x51F, 0x521, 0x523, 0x525,
    0x527, 0x529, 0x52B, 0x52D, 0x52F, 0x1E01, 0x1E03, 0x1E05, 0x1E07,
    0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, 0x1E17, 0x1E19,
    0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27, 0x1E29, 0x1E2B,
    0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39, 0x1E3B, 0x1E3D,
    0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D, 0x1E4F,
    0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61,
    0x1E63, 0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73,
    0x1E75, 0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85,
    0x1E87, 0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E9F, 0x1EA1,
    0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1, 0x1EB3,
    0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5,
    0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, 0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7,
    0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9,
    0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9, 0x1EFB,
    0x1EFD, 0x1FB6, 0x1FB7, 0x1FBE, 0x1FC6, 0x1FC7, 0x1FD6, 0x1FD7, 0x1FF6,
    0x1FF7, 0x210A, 0x210E, 0x210F, 0x2113, 0x212F, 0x2134, 0x2139, 0x213C,
    0x213D, 0x214E, 0x2184, 0x2C61, 0x2C65, 0x2C66, 0x2C68, 0x2C6A, 0x2C6C,
    0x2C71, 0x2C73, 0x2C74, 0x2C81, 0x2C83, 0x2C85, 0x2C87, 0x2C89, 0x2C8B,
    0x2C8D, 0x2C8F, 0x2C91, 0x2C93, 0x2C95, 0x2C97, 0x2C99, 0x2C9B, 0x2C9D,
    0x2C9F, 0x2CA1, 0x2CA3, 0x2CA5, 0x2CA7, 0x2CA9, 0x2CAB, 0x2CAD, 0x2CAF,
    0x2CB1, 0x2CB3, 0x2CB5, 0x2CB7, 0x2CB9, 0x2CBB, 0x2CBD, 0x2CBF, 0x2CC1,
    0x2CC3, 0x2CC5, 0x2CC7, 0x2CC9, 0x2CCB, 0x2CCD, 0x2CCF, 0x2CD1, 0x2CD3,
    0x2CD5, 0x2CD7, 0x2CD9, 0x2CDB, 0x2CDD, 0x2CDF, 0x2CE1, 0x2CE3, 0x2CE4,
    0x2CEC, 0x2CEE, 0x2CF3, 0x2D27, 0x2D2D, 0xA641, 0xA643, 0xA645, 0xA647,
    0xA649, 0xA64B, 0xA64D, 0xA64F, 0xA651, 0xA653, 0xA655, 0xA657, 0xA659,
    0xA65B, 0xA65D, 0xA65F, 0xA661, 0xA663, 0xA665, 0xA667, 0xA669, 0xA66B,
    0xA66D, 0xA681, 0xA683, 0xA685, 0xA687, 0xA689, 0xA68B, 0xA68D, 0xA68F,
    0xA691, 0xA693, 0xA695, 0xA697, 0xA699, 0xA69B, 0xA723, 0xA725, 0xA727,
    0xA729, 0xA72B, 0xA72D, 0xA733, 0xA735, 0xA737, 0xA739, 0xA73B, 0xA73D,
    0xA73F, 0xA741, 0xA743, 0xA745, 0xA747, 0xA749, 0xA74B, 0xA74D, 0xA74F,
    0xA751, 0xA753, 0xA755, 0xA757, 0xA759, 0xA75B, 0xA75D, 0xA75F, 0xA761,
    0xA763, 0xA765, 0xA767, 0xA769, 0xA76B, 0xA76D, 0xA76F, 0xA77A, 0xA77C,
    0xA77F, 0xA781, 0xA783, 0xA785, 0xA787, 0xA78C, 0xA78E, 0xA791, 0xA797,
    0xA799, 0xA79B, 0xA79D, 0xA79F, 0xA7A1, 0xA7A3, 0xA7A5, 0xA7A7, 0xA7A9,
    0xA7AF, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD, 0xA7BF, 0xA7C1, 0xA7C3,
    0xA7C8, 0xA7CA, 0xA7D1, 0xA7D3, 0xA7D5, 0xA7D7, 0xA7D9, 0xA7F6, 0xA7FA
#if CHRBITS > 16
    ,0x105BB, 0x105BC, 0x1D4BB, 0x1D7CB
#endif
};

#define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr))

/*
 * Unicode: uppercase characters.
 */

static const crange upperRangeTable[] = {
    {0x41, 0x5A}, {0xC0, 0xD6}, {0xD8, 0xDE}, {0x189, 0x18B},
    {0x18E, 0x191}, {0x196, 0x198}, {0x1B1, 0x1B3}, {0x1F6, 0x1F8},
    {0x243, 0x246}, {0x388, 0x38A}, {0x391, 0x3A1}, {0x3A3, 0x3AB},
    {0x3D2, 0x3D4}, {0x3FD, 0x42F}, {0x531, 0x556}, {0x10A0, 0x10C5},
    {0x13A0, 0x13F5}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF}, {0x1F08, 0x1F0F},
    {0x1F18, 0x1F1D}, {0x1F28, 0x1F2F}, {0x1F38, 0x1F3F}, {0x1F48, 0x1F4D},
    {0x1F68, 0x1F6F}, {0x1FB8, 0x1FBB}, {0x1FC8, 0x1FCB}, {0x1FD8, 0x1FDB},
    {0x1FE8, 0x1FEC}, {0x1FF8, 0x1FFB}, {0x210B, 0x210D}, {0x2110, 0x2112},
    {0x2119, 0x211D}, {0x212A, 0x212D}, {0x2130, 0x2133}, {0x2C00, 0x2C2F},
    {0x2C62, 0x2C64}, {0x2C6D, 0x2C70}, {0x2C7E, 0x2C80}, {0xA7AA, 0xA7AE},
    {0xA7B0, 0xA7B4}, {0xA7C4, 0xA7C7}, {0xFF21, 0xFF3A}
#if CHRBITS > 16
    ,{0x10400, 0x10427}, {0x104B0, 0x104D3}, {0x10570, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10C80, 0x10CB2}, {0x118A0, 0x118BF}, {0x16E40, 0x16E5F},
    {0x1D400, 0x1D419}, {0x1D434, 0x1D44D}, {0x1D468, 0x1D481}, {0x1D4A9, 0x1D4AC},
    {0x1D4AE, 0x1D4B5}, {0x1D4D0, 0x1D4E9}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514},
    {0x1D516, 0x1D51C}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D54A, 0x1D550},
    {0x1D56C, 0x1D585}, {0x1D5A0, 0x1D5B9}, {0x1D5D4, 0x1D5ED}, {0x1D608, 0x1D621},
    {0x1D63C, 0x1D655}, {0x1D670, 0x1D689}, {0x1D6A8, 0x1D6C0}, {0x1D6E2, 0x1D6FA},
    {0x1D71C, 0x1D734}, {0x1D756, 0x1D76E}, {0x1D790, 0x1D7A8}, {0x1E900, 0x1E921}
#endif
};

#define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange))

static const chr upperCharTable[] = {
    0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110,
    0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122,
    0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134,
    0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147,
    0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A,
    0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C,
    0x16E, 0x170, 0x172, 0x174, 0x176, 0x178, 0x179, 0x17B, 0x17D,
    0x181, 0x182, 0x184, 0x186, 0x187, 0x193, 0x194, 0x19C, 0x19D,
    0x19F, 0x1A0, 0x1A2, 0x1A4, 0x1A6, 0x1A7, 0x1A9, 0x1AC, 0x1AE,
    0x1AF, 0x1B5, 0x1B7, 0x1B8, 0x1BC, 0x1C4, 0x1C7, 0x1CA, 0x1CD,
    0x1CF, 0x1D1, 0x1D3, 0x1D5, 0x1D7, 0x1D9, 0x1DB, 0x1DE, 0x1E0,
    0x1E2, 0x1E4, 0x1E6, 0x1E8, 0x1EA, 0x1EC, 0x1EE, 0x1F1, 0x1F4,
    0x1FA, 0x1FC, 0x1FE, 0x200, 0x202, 0x204, 0x206, 0x208, 0x20A,
    0x20C, 0x20E, 0x210, 0x212, 0x214, 0x216, 0x218, 0x21A, 0x21C,
    0x21E, 0x220, 0x222, 0x224, 0x226, 0x228, 0x22A, 0x22C, 0x22E,
    0x230, 0x232, 0x23A, 0x23B, 0x23D, 0x23E, 0x241, 0x248, 0x24A,
    0x24C, 0x24E, 0x370, 0x372, 0x376, 0x37F, 0x386, 0x38C, 0x38E,
    0x38F, 0x3CF, 0x3D8, 0x3DA, 0x3DC, 0x3DE, 0x3E0, 0x3E2, 0x3E4,
    0x3E6, 0x3E8, 0x3EA, 0x3EC, 0x3EE, 0x3F4, 0x3F7, 0x3F9, 0x3FA,
    0x460, 0x462, 0x464, 0x466, 0x468, 0x46A, 0x46C, 0x46E, 0x470,
    0x472, 0x474, 0x476, 0x478, 0x47A, 0x47C, 0x47E, 0x480, 0x48A,
    0x48C, 0x48E, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49A, 0x49C,
    0x49E, 0x4A0, 0x4A2, 0x4A4, 0x4A6, 0x4A8, 0x4AA, 0x4AC, 0x4AE,
    0x4B0, 0x4B2, 0x4B4, 0x4B6, 0x4B8, 0x4BA, 0x4BC, 0x4BE, 0x4C0,
    0x4C1, 0x4C3, 0x4C5, 0x4C7, 0x4C9, 0x4CB, 0x4CD, 0x4D0, 0x4D2,
    0x4D4, 0x4D6, 0x4D8, 0x4DA, 0x4DC, 0x4DE, 0x4E0, 0x4E2, 0x4E4,
    0x4E6, 0x4E8, 0x4EA, 0x4EC, 0x4EE, 0x4F0, 0x4F2, 0x4F4, 0x4F6,
    0x4F8, 0x4FA, 0x4FC, 0x4FE, 0x500, 0x502, 0x504, 0x506, 0x508,
    0x50A, 0x50C, 0x50E, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51A,
    0x51C, 0x51E, 0x520, 0x522, 0x524, 0x526, 0x528, 0x52A, 0x52C,
    0x52E, 0x10C7, 0x10CD, 0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08, 0x1E0A,
    0x1E0C, 0x1E0E, 0x1E10, 0x1E12, 0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C,
    0x1E1E, 0x1E20, 0x1E22, 0x1E24, 0x1E26, 0x1E28, 0x1E2A, 0x1E2C, 0x1E2E,
    0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38, 0x1E3A, 0x1E3C, 0x1E3E, 0x1E40,
    0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E, 0x1E50, 0x1E52,
    0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62, 0x1E64,
    0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74, 0x1E76,
    0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86, 0x1E88,
    0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1E9E, 0x1EA0, 0x1EA2,
    0x1EA4, 0x1EA6, 0x1EA8, 0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4,
    0x1EB6, 0x1EB8, 0x1EBA, 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6,
    0x1EC8, 0x1ECA, 0x1ECC, 0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8,
    0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8, 0x1EEA,
    0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8, 0x1EFA, 0x1EFC,
    0x1EFE, 0x1F59, 0x1F5B, 0x1F5D, 0x1F5F, 0x2102, 0x2107, 0x2115, 0x2124,
    0x2126, 0x2128, 0x213E, 0x213F, 0x2145, 0x2183, 0x2C60, 0x2C67, 0x2C69,
    0x2C6B, 0x2C72, 0x2C75, 0x2C82, 0x2C84, 0x2C86, 0x2C88, 0x2C8A, 0x2C8C,
    0x2C8E, 0x2C90, 0x2C92, 0x2C94, 0x2C96, 0x2C98, 0x2C9A, 0x2C9C, 0x2C9E,
    0x2CA0, 0x2CA2, 0x2CA4, 0x2CA6, 0x2CA8, 0x2CAA, 0x2CAC, 0x2CAE, 0x2CB0,
    0x2CB2, 0x2CB4, 0x2CB6, 0x2CB8, 0x2CBA, 0x2CBC, 0x2CBE, 0x2CC0, 0x2CC2,
    0x2CC4, 0x2CC6, 0x2CC8, 0x2CCA, 0x2CCC, 0x2CCE, 0x2CD0, 0x2CD2, 0x2CD4,
    0x2CD6, 0x2CD8, 0x2CDA, 0x2CDC, 0x2CDE, 0x2CE0, 0x2CE2, 0x2CEB, 0x2CED,
    0x2CF2, 0xA640, 0xA642, 0xA644, 0xA646, 0xA648, 0xA64A, 0xA64C, 0xA64E,
    0xA650, 0xA652, 0xA654, 0xA656, 0xA658, 0xA65A, 0xA65C, 0xA65E, 0xA660,
    0xA662, 0xA664, 0xA666, 0xA668, 0xA66A, 0xA66C, 0xA680, 0xA682, 0xA684,
    0xA686, 0xA688, 0xA68A, 0xA68C, 0xA68E, 0xA690, 0xA692, 0xA694, 0xA696,
    0xA698, 0xA69A, 0xA722, 0xA724, 0xA726, 0xA728, 0xA72A, 0xA72C, 0xA72E,
    0xA732, 0xA734, 0xA736, 0xA738, 0xA73A, 0xA73C, 0xA73E, 0xA740, 0xA742,
    0xA744, 0xA746, 0xA748, 0xA74A, 0xA74C, 0xA74E, 0xA750, 0xA752, 0xA754,
    0xA756, 0xA758, 0xA75A, 0xA75C, 0xA75E, 0xA760, 0xA762, 0xA764, 0xA766,
    0xA768, 0xA76A, 0xA76C, 0xA76E, 0xA779, 0xA77B, 0xA77D, 0xA77E, 0xA780,
    0xA782, 0xA784, 0xA786, 0xA78B, 0xA78D, 0xA790, 0xA792, 0xA796, 0xA798,
    0xA79A, 0xA79C, 0xA79E, 0xA7A0, 0xA7A2, 0xA7A4, 0xA7A6, 0xA7A8, 0xA7B6,
    0xA7B8, 0xA7BA, 0xA7BC, 0xA7BE, 0xA7C0, 0xA7C2, 0xA7C9, 0xA7D0, 0xA7D6,
    0xA7D8, 0xA7F5
#if CHRBITS > 16
    ,0x10594, 0x10595, 0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504,
    0x1D505, 0x1D538, 0x1D539, 0x1D546, 0x1D7CA
#endif
};

#define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr))

/*
 * Unicode: unicode print characters excluding space.
 */

static const crange graphRangeTable[] = {
    {0x21, 0x7E}, {0xA1, 0xAC}, {0xAE, 0x377}, {0x37A, 0x37F},
    {0x384, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x52F}, {0x531, 0x556},
    {0x559, 0x58A}, {0x58D, 0x58F}, {0x591, 0x5C7}, {0x5D0, 0x5EA},
    {0x5EF, 0x5F4}, {0x606, 0x61B}, {0x61D, 0x6DC}, {0x6DE, 0x70D},
    {0x710, 0x74A}, {0x74D, 0x7B1}, {0x7C0, 0x7FA}, {0x7FD, 0x82D},
    {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x870, 0x88E},
    {0x898, 0x8E1}, {0x8E3, 0x983}, {0x985, 0x98C}, {0x993, 0x9A8},
    {0x9AA, 0x9B0}, {0x9B6, 0x9B9}, {0x9BC, 0x9C4}, {0x9CB, 0x9CE},
    {0x9DF, 0x9E3}, {0x9E6, 0x9FE}, {0xA01, 0xA03}, {0xA05, 0xA0A},
    {0xA13, 0xA28}, {0xA2A, 0xA30}, {0xA3E, 0xA42}, {0xA4B, 0xA4D},
    {0xA59, 0xA5C}, {0xA66, 0xA76}, {0xA81, 0xA83}, {0xA85, 0xA8D},
    {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9},
    {0xABC, 0xAC5}, {0xAC7, 0xAC9}, {0xACB, 0xACD}, {0xAE0, 0xAE3},
    {0xAE6, 0xAF1}, {0xAF9, 0xAFF}, {0xB01, 0xB03}, {0xB05, 0xB0C},
    {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, {0xB3C, 0xB44},
    {0xB4B, 0xB4D}, {0xB55, 0xB57}, {0xB5F, 0xB63}, {0xB66, 0xB77},
    {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, {0xBA8, 0xBAA},
    {0xBAE, 0xBB9}, {0xBBE, 0xBC2}, {0xBC6, 0xBC8}, {0xBCA, 0xBCD},
    {0xBE6, 0xBFA}, {0xC00, 0xC0C}, {0xC0E, 0xC10}, {0xC12, 0xC28},
    {0xC2A, 0xC39}, {0xC3C, 0xC44}, {0xC46, 0xC48}, {0xC4A, 0xC4D},
    {0xC58, 0xC5A}, {0xC60, 0xC63}, {0xC66, 0xC6F}, {0xC77, 0xC8C},
    {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9},
    {0xCBC, 0xCC4}, {0xCC6, 0xCC8}, {0xCCA, 0xCCD}, {0xCE0, 0xCE3},
    {0xCE6, 0xCEF}, {0xCF1, 0xCF3}, {0xD00, 0xD0C}, {0xD0E, 0xD10},
    {0xD12, 0xD44}, {0xD46, 0xD48}, {0xD4A, 0xD4F}, {0xD54, 0xD63},
    {0xD66, 0xD7F}, {0xD81, 0xD83}, {0xD85, 0xD96}, {0xD9A, 0xDB1},
    {0xDB3, 0xDBB}, {0xDC0, 0xDC6}, {0xDCF, 0xDD4}, {0xDD8, 0xDDF},
    {0xDE6, 0xDEF}, {0xDF2, 0xDF4}, {0xE01, 0xE3A}, {0xE3F, 0xE5B},
    {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA7, 0xEBD}, {0xEC0, 0xEC4},
    {0xEC8, 0xECE}, {0xED0, 0xED9}, {0xEDC, 0xEDF}, {0xF00, 0xF47},
    {0xF49, 0xF6C}, {0xF71, 0xF97}, {0xF99, 0xFBC}, {0xFBE, 0xFCC},
    {0xFCE, 0xFDA}, {0x1000, 0x10C5}, {0x10D0, 0x1248}, {0x124A, 0x124D},
    {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
    {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C2, 0x12C5},
    {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
    {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
    {0x1400, 0x167F}, {0x1681, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x1715},
    {0x171F, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770},
    {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180D},
    {0x180F, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA}, {0x18B0, 0x18F5},
    {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1944, 0x196D},
    {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA},
    {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89},
    {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C},

    {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49},
    {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA},
    {0x1D00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
    {0x1F50, 0x1F57}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4},
    {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4},
    {0x1FF6, 0x1FFE}, {0x2010, 0x2027}, {0x2030, 0x205E}, {0x2074, 0x208E},
    {0x2090, 0x209C}, {0x20A0, 0x20C0}, {0x20D0, 0x20F0}, {0x2100, 0x218B},
    {0x2190, 0x2426}, {0x2440, 0x244A}, {0x2460, 0x2B73}, {0x2B76, 0x2B95},

    {0x2B97, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D30, 0x2D67}, {0x2D7F, 0x2D96},
    {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
    {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
    {0x2DE0, 0x2E5D}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5},
    {0x2FF0, 0x2FFB}, {0x3001, 0x303F}, {0x3041, 0x3096}, {0x3099, 0x30FF},
    {0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31F0, 0x321E},
    {0x3220, 0xA48C}, {0xA490, 0xA4C6}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
    {0xA700, 0xA7CA}, {0xA7D5, 0xA7D9}, {0xA7F2, 0xA82C}, {0xA830, 0xA839},
    {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, {0xA8E0, 0xA953},
    {0xA95F, 0xA97C}, {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE},
    {0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
    {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, {0xAB11, 0xAB16},
    {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB6B}, {0xAB70, 0xABED},
    {0xABF0, 0xABF9}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
    {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
    {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F},

    {0xFD92, 0xFDC7}, {0xFDF0, 0xFE19}, {0xFE20, 0xFE52}, {0xFE54, 0xFE66},
    {0xFE68, 0xFE6B}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF01, 0xFFBE},
    {0xFFC2, 0xFFC7}, {0xFFCA, 0xFFCF}, {0xFFD2, 0xFFD7}, {0xFFDA, 0xFFDC},
    {0xFFE0, 0xFFE6}, {0xFFE8, 0xFFEE}
#if CHRBITS > 16
    ,{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003F, 0x1004D},
    {0x10050, 0x1005D}, {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
    {0x10137, 0x1018E}, {0x10190, 0x1019C}, {0x101D0, 0x101FD}, {0x10280, 0x1029C},
    {0x102A0, 0x102D0}, {0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
    {0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
    {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, {0x104D8, 0x104FB},
    {0x10500, 0x10527}, {0x10530, 0x10563}, {0x1056F, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10597, 0x105A1}, {0x105A3, 0x105B1}, {0x105B3, 0x105B9},
    {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785},
    {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805}, {0x1080A, 0x10835},
    {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF}, {0x108E0, 0x108F2},
    {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x10980, 0x109B7}, {0x109BC, 0x109CF},
    {0x109D2, 0x10A03}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
    {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58}, {0x10A60, 0x10A9F},
    {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55},
    {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
    {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27},
    {0x10D30, 0x10D39}, {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD},
    {0x10EFD, 0x10F27}, {0x10F30, 0x10F59}, {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB},
    {0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110BC},
    {0x110BE, 0x110C2}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11134},
    {0x11136, 0x11147}, {0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
    {0x11200, 0x11211}, {0x11213, 0x11241}, {0x11280, 0x11286}, {0x1128A, 0x1128D},
    {0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
    {0x11300, 0x11303}, {0x11305, 0x1130C}, {0x11313, 0x11328}, {0x1132A, 0x11330},
    {0x11335, 0x11339}, {0x1133B, 0x11344}, {0x1134B, 0x1134D}, {0x1135D, 0x11363},
    {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x1145B}, {0x1145D, 0x11461},
    {0x11480, 0x114C7}, {0x114D0, 0x114D9}, {0x11580, 0x115B5}, {0x115B8, 0x115DD},
    {0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9},
    {0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B}, {0x11730, 0x11746},
    {0x11800, 0x1183B}, {0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x1190C, 0x11913},
    {0x11918, 0x11935}, {0x1193B, 0x11946}, {0x11950, 0x11959}, {0x119A0, 0x119A7},
    {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, {0x11A00, 0x11A47}, {0x11A50, 0x11AA2},
    {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
    {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
    {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D0B, 0x11D36}, {0x11D3F, 0x11D47},
    {0x11D50, 0x11D59}, {0x11D60, 0x11D65}, {0x11D6A, 0x11D8E}, {0x11D93, 0x11D98},
    {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8}, {0x11F00, 0x11F10}, {0x11F12, 0x11F3A},
    {0x11F3E, 0x11F59}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399}, {0x12400, 0x1246E},
    {0x12470, 0x12474}, {0x12480, 0x12543}, {0x12F90, 0x12FF2}, {0x13000, 0x1342F},
    {0x13440, 0x13455}, {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E},
    {0x16A60, 0x16A69}, {0x16A6E, 0x16ABE}, {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED},
    {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61},
    {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A},
    {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F}, {0x16FE0, 0x16FE4}, {0x17000, 0x187F7},

    {0x18800, 0x18CD5}, {0x18D00, 0x18D08}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB},
    {0x1B000, 0x1B122}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB},
    {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99},
    {0x1BC9C, 0x1BC9F}, {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1CF50, 0x1CFC3},
    {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D172}, {0x1D17B, 0x1D1EA},
    {0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356},
    {0x1D360, 0x1D378}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D4A9, 0x1D4AC},
    {0x1D4AE, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A},
    {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
    {0x1D540, 0x1D544}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB},
    {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1DF00, 0x1DF1E},
    {0x1DF25, 0x1DF2A}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021},
    {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D},
    {0x1E140, 0x1E149}, {0x1E290, 0x1E2AE}, {0x1E2C0, 0x1E2F9}, {0x1E4D0, 0x1E4F9},
    {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4},
    {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1EC71, 0x1ECB4},
    {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE29, 0x1EE32},
    {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
    {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
    {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1F000, 0x1F02B},
    {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CF},
    {0x1F0D1, 0x1F0F5}, {0x1F100, 0x1F1AD}, {0x1F1E6, 0x1F202}, {0x1F210, 0x1F23B},
    {0x1F240, 0x1F248}, {0x1F260, 0x1F265}, {0x1F300, 0x1F6D7}, {0x1F6DC, 0x1F6EC},
    {0x1F6F0, 0x1F6FC}, {0x1F700, 0x1F776}, {0x1F77B, 0x1F7D9}, {0x1F7E0, 0x1F7EB},
    {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, {0x1F860, 0x1F887},
    {0x1F890, 0x1F8AD}, {0x1F900, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0x1FA70, 0x1FA7C},
    {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD}, {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB},
    {0x1FAE0, 0x1FAE8}, {0x1FAF0, 0x1FAF8}, {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA},
    {0x1FBF0, 0x1FBF9}, {0x20000, 0x2A6DF}, {0x2A700, 0x2B739}, {0x2B740, 0x2B81D},
    {0x2B820, 0x2CEA1}, {0x2CEB0, 0x2EBE0}, {0x2F800, 0x2FA1D}, {0x30000, 0x3134A},

    {0x31350, 0x323AF}, {0xE0100, 0xE01EF}
#endif
};

#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))

static const chr graphCharTable[] = {
    0x38C, 0x85E, 0x98F, 0x990, 0x9B2, 0x9C7, 0x9C8, 0x9D7, 0x9DC,
    0x9DD, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36, 0xA38, 0xA39,
    0xA3C, 0xA47, 0xA48, 0xA51, 0xA5E, 0xAB2, 0xAB3, 0xAD0, 0xB0F,
    0xB10, 0xB32, 0xB33, 0xB47, 0xB48, 0xB5C, 0xB5D, 0xB82, 0xB83,
    0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0, 0xBD7,
    0xC55, 0xC56, 0xC5D, 0xCD5, 0xCD6, 0xCDD, 0xCDE, 0xDBD, 0xDCA,

    0xDD6, 0xE81, 0xE82, 0xE84, 0xEA5, 0xEC6, 0x10C7, 0x10CD, 0x1258,
    0x12C0, 0x1772, 0x1773, 0x1940, 0x1F59, 0x1F5B, 0x1F5D, 0x2070, 0x2071,
    0x2D27, 0x2D2D, 0x2D6F, 0x2D70, 0xA7D0, 0xA7D1, 0xA7D3, 0xFB3E, 0xFB40,

    0xFB41, 0xFB43, 0xFB44, 0xFDCF, 0xFFFC, 0xFFFD
#if CHRBITS > 16
    ,0x1003C, 0x1003D, 0x101A0, 0x10594, 0x10595, 0x105BB, 0x105BC, 0x10808, 0x10837,
    0x10838, 0x1083C, 0x108F4, 0x108F5, 0x1093F, 0x10A05, 0x10A06, 0x10EB0, 0x10EB1,
    0x11288, 0x1130F, 0x11310, 0x11332, 0x11333, 0x11347, 0x11348, 0x11350, 0x11357,
    0x11909, 0x11915, 0x11916, 0x11937, 0x11938, 0x11D08, 0x11D09, 0x11D3A, 0x11D3C,
    0x11D3D, 0x11D67, 0x11D68, 0x11D90, 0x11D91, 0x11FB0, 0x16FF0, 0x16FF1, 0x1AFFD,
    0x1AFFE, 0x1B132, 0x1B155, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB,
    0x1D546, 0x1E023, 0x1E024, 0x1E08F, 0x1E14E, 0x1E14F, 0x1E2FF, 0x1E7ED, 0x1E7EE,
    0x1E95E, 0x1E95F, 0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B, 0x1EE42,
    0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B,
    0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E, 0x1EEF0, 0x1EEF1, 0x1F250,
    0x1F251, 0x1F7F0, 0x1F8B0, 0x1F8B1
#endif
};

#define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr))

/*
 *	End of auto-generated Unicode character ranges declarations.







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
<
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
<
|
<
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
<
<
|
|
<
|
|
|
|
|
>
|
|
|
|
<
<
|
|
<
<
<
|
|
|
|
|
|
<






|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
<
|
|
|
>

|
<
|
|
|
|
|
|
<
<
<
|










|
|
|

|
|






|

|










|
|
|
|
|
|
|
|
|
|

|
|
|
|
<
<
|














|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
<
|
|






|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
<
|










|





|
|









|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
<
<
|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

|










|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|

|
|










|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|

|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
<
|
|
|
<
|
<
|
|
|
|
<
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
|
<
|
|
|
<
|
|
<
>
|






|
|
|
|
|
|
>
|
|
<
>
|

|
|
|
<
|
|
|
|
|
<
|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209

210
211
212
213
214
215

216
217
218
219
220
221
222
223


224
225

226
227
228
229
230
231
232
233
234
235


236
237



238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270

271
272
273
274
275
276



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327


328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436


437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705


706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722

723
724
725

726

727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752






753

754
755
756

757
758

759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781

782
783
784
785
786

787
788
789
790
791
792
793
794
 */

/*
 * Unicode: alphabetic characters.
 */

static const crange alphaRangeTable[] = {
    {0x41, 0x5a}, {0x61, 0x7a}, {0xc0, 0xd6}, {0xd8, 0xf6},
    {0xf8, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, {0x370, 0x374},
    {0x37a, 0x37d}, {0x388, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x3f5},
    {0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x560, 0x588},
    {0x5d0, 0x5ea}, {0x5ef, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3},
    {0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea},
    {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86a}, {0x8a0, 0x8b4},
    {0x8b6, 0x8bd}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980},
    {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9},
    {0x9df, 0x9e1}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30},
    {0xa59, 0xa5c}, {0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91},
    {0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c},
    {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61},
    {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa},
    {0xbae, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
    {0xc2a, 0xc39}, {0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90},
    {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c},
    {0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd54, 0xd56}, {0xd5f, 0xd61},
    {0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb},
    {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97},
    {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4},
    {0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c},
    {0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070},
    {0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248},
    {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288},
    {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be},
    {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315},
    {0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd},
    {0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea},
    {0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731},
    {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3},
    {0x1820, 0x1878}, {0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5},
    {0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},

    {0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33},
    {0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23},
    {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1c90, 0x1cba},
    {0x1cbd, 0x1cbf}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf},
    {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d},
    {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc},
    {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb},
    {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2090, 0x209c},
    {0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x212f, 0x2139},
    {0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e},
    {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25}, {0x2d30, 0x2d67},
    {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6},
    {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6},
    {0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309d, 0x309f},
    {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312f}, {0x3131, 0x318e},
    {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5}, {0x4e00, 0x9fef},
    {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c}, {0xa610, 0xa61f},
    {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5}, {0xa717, 0xa71f},
    {0xa722, 0xa788}, {0xa78b, 0xa7b9}, {0xa7f7, 0xa801}, {0xa803, 0xa805},
    {0xa807, 0xa80a}, {0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3},
    {0xa8f2, 0xa8f7}, {0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c},
    {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe},
    {0xaa00, 0xaa28}, {0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76},
    {0xaa7e, 0xaaaf}, {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea},
    {0xaaf2, 0xaaf4}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16},
    {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65},
    {0xab70, 0xabe2}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb},
    {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17},
    {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1},
    {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb},
    {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a},
    {0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7},
    {0xffda, 0xffdc}
#if CHRBITS > 16
    ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
    {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0},
    {0x10300, 0x1031f}, {0x1032d, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
    {0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d},
    {0x104b0, 0x104d3}, {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563},

    {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},

    {0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e},
    {0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7},
    {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a60, 0x10a7c},
    {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35},
    {0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48},
    {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10d00, 0x10d23}, {0x10f00, 0x10f1c},

    {0x10f30, 0x10f45}, {0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8},
    {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4},
    {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d},
    {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c},
    {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361},
    {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af}, {0x11580, 0x115ae},
    {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa}, {0x11700, 0x1171a},
    {0x11800, 0x1182b}, {0x118a0, 0x118df}, {0x11a0b, 0x11a32}, {0x11a5c, 0x11a83},


    {0x11a86, 0x11a89}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c2e},
    {0x11c72, 0x11c8f}, {0x11d00, 0x11d06}, {0x11d0b, 0x11d30}, {0x11d60, 0x11d65},

    {0x11d6a, 0x11d89}, {0x11ee0, 0x11ef2}, {0x12000, 0x12399}, {0x12480, 0x12543},
    {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
    {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77},
    {0x16b7d, 0x16b8f}, {0x16e40, 0x16e7f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f},
    {0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb},
    {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
    {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9},
    {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514},
    {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
    {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da},


    {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e},
    {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2},



    {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943}, {0x1ee00, 0x1ee03},
    {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f},
    {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c},
    {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9},
    {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d},
    {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}

#endif
};

#define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))

static const chr alphaCharTable[] = {
    0xaa, 0xb5, 0xba, 0x2ec, 0x2ee, 0x376, 0x377, 0x37f, 0x386,
    0x38c, 0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef,
    0x6ff, 0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828,
    0x93d, 0x950, 0x98f, 0x990, 0x9b2, 0x9bd, 0x9ce, 0x9dc, 0x9dd,
    0x9f0, 0x9f1, 0x9fc, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36,
    0xa38, 0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1,
    0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71,
    0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0,
    0xc3d, 0xc60, 0xc61, 0xc80, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1,
    0xcf2, 0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84,
    0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2,
    0xeb3, 0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e,
    0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae,
    0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f,
    0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184,

    0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b,
    0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa8fe, 0xa9cf, 0xaa7a, 0xaab1,
    0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43,
    0xfb44
#if CHRBITS > 16
    ,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be,

    0x109bf, 0x10a00, 0x10f27, 0x11144, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f,
    0x11310, 0x11332, 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644,
    0x118ff, 0x11a00, 0x11a3a, 0x11a50, 0x11a9d, 0x11c40, 0x11d08, 0x11d09, 0x11d46,
    0x11d67, 0x11d68, 0x11d98, 0x16f50, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2,
    0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39,
    0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57,



    0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e
#endif
};

#define NUM_ALPHA_CHAR (sizeof(alphaCharTable)/sizeof(chr))

/*
 * Unicode: control characters.
 */

static const crange controlRangeTable[] = {
    {0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f},
    {0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff},
    {0xfff9, 0xfffb}
#if CHRBITS > 16
    ,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd},
    {0x100000, 0x10fffd}
#endif
};

#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))

static const chr controlCharTable[] = {
    0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff
#if CHRBITS > 16
    ,0x110bd, 0x110cd, 0xe0001
#endif
};

#define NUM_CONTROL_CHAR (sizeof(controlCharTable)/sizeof(chr))

/*
 * Unicode: decimal digit characters.
 */

static const crange digitRangeTable[] = {
    {0x30, 0x39}, {0x660, 0x669}, {0x6f0, 0x6f9}, {0x7c0, 0x7c9},
    {0x966, 0x96f}, {0x9e6, 0x9ef}, {0xa66, 0xa6f}, {0xae6, 0xaef},
    {0xb66, 0xb6f}, {0xbe6, 0xbef}, {0xc66, 0xc6f}, {0xce6, 0xcef},
    {0xd66, 0xd6f}, {0xde6, 0xdef}, {0xe50, 0xe59}, {0xed0, 0xed9},
    {0xf20, 0xf29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x17e0, 0x17e9},
    {0x1810, 0x1819}, {0x1946, 0x194f}, {0x19d0, 0x19d9}, {0x1a80, 0x1a89},
    {0x1a90, 0x1a99}, {0x1b50, 0x1b59}, {0x1bb0, 0x1bb9}, {0x1c40, 0x1c49},
    {0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909},
    {0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9},
    {0xff10, 0xff19}
#if CHRBITS > 16
    ,{0x104a0, 0x104a9}, {0x10d30, 0x10d39}, {0x11066, 0x1106f}, {0x110f0, 0x110f9},
    {0x11136, 0x1113f}, {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459},
    {0x114d0, 0x114d9}, {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739},
    {0x118e0, 0x118e9}, {0x11c50, 0x11c59}, {0x11d50, 0x11d59}, {0x11da0, 0x11da9},


    {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff}, {0x1e950, 0x1e959}
#endif
};

#define NUM_DIGIT_RANGE (sizeof(digitRangeTable)/sizeof(crange))

/*
 * no singletons of digit characters.
 */

/*
 * Unicode: punctuation characters.
 */

static const crange punctRangeTable[] = {
    {0x21, 0x23}, {0x25, 0x2a}, {0x2c, 0x2f}, {0x5b, 0x5d},
    {0x55a, 0x55f}, {0x66a, 0x66d}, {0x700, 0x70d}, {0x7f7, 0x7f9},
    {0x830, 0x83e}, {0xf04, 0xf12}, {0xf3a, 0xf3d}, {0xfd0, 0xfd4},
    {0x104a, 0x104f}, {0x1360, 0x1368}, {0x16eb, 0x16ed}, {0x17d4, 0x17d6},
    {0x17d8, 0x17da}, {0x1800, 0x180a}, {0x1aa0, 0x1aa6}, {0x1aa8, 0x1aad},
    {0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7},
    {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e},
    {0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998},
    {0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e4e},
    {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f},
    {0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd},
    {0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61},
    {0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d},
    {0xff5f, 0xff65}
#if CHRBITS > 16
    ,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f},
    {0x10b99, 0x10b9c}, {0x10f55, 0x10f59}, {0x11047, 0x1104d}, {0x110be, 0x110c1},
    {0x11140, 0x11143}, {0x111c5, 0x111c8}, {0x111dd, 0x111df}, {0x11238, 0x1123d},
    {0x1144b, 0x1144f}, {0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c},
    {0x1173c, 0x1173e}, {0x11a3f, 0x11a46}, {0x11a9a, 0x11a9c}, {0x11a9e, 0x11aa2},

    {0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x16e97, 0x16e9a},
    {0x1da87, 0x1da8b}
#endif
};

#define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange))

static const chr punctCharTable[] = {
    0x3a, 0x3b, 0x3f, 0x40, 0x5f, 0x7b, 0x7d, 0xa1, 0xa7,
    0xab, 0xb6, 0xb7, 0xbb, 0xbf, 0x37e, 0x387, 0x589, 0x58a,
    0x5be, 0x5c0, 0x5c3, 0x5c6, 0x5f3, 0x5f4, 0x609, 0x60a, 0x60c,
    0x60d, 0x61b, 0x61e, 0x61f, 0x6d4, 0x85e, 0x964, 0x965, 0x970,
    0x9fd, 0xa76, 0xaf0, 0xc84, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14,
    0xf85, 0xfd9, 0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c,
    0x1735, 0x1736, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3,
    0x207d, 0x207e, 0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc,
    0x29fd, 0x2cfe, 0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe,
    0xa4ff, 0xa673, 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f,
    0xa9de, 0xa9df, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f,
    0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f,
    0xff5b, 0xff5d
#if CHRBITS > 16
    ,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc,
    0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x1183b,
    0x11c70, 0x11c71, 0x11ef7, 0x11ef8, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f,

    0x1e95e, 0x1e95f
#endif
};

#define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr))

/*
 * Unicode: white space characters.
 */

static const crange spaceRangeTable[] = {
    {0x9, 0xd}, {0x2000, 0x200b}
};

#define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange))

static const chr spaceCharTable[] = {
    0x20, 0xa0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f,
    0x2060, 0x3000, 0xfeff
};

#define NUM_SPACE_CHAR (sizeof(spaceCharTable)/sizeof(chr))

/*
 * Unicode: lowercase characters.
 */

static const crange lowerRangeTable[] = {
    {0x61, 0x7a}, {0xdf, 0xf6}, {0xf8, 0xff}, {0x17e, 0x180},
    {0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293},
    {0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7},
    {0x3ef, 0x3f3}, {0x430, 0x45f}, {0x560, 0x588}, {0x10d0, 0x10fa},
    {0x10fd, 0x10ff}, {0x13f8, 0x13fd}, {0x1c80, 0x1c88}, {0x1d00, 0x1d2b},
    {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d}, {0x1eff, 0x1f07},
    {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, {0x1f40, 0x1f45},
    {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, {0x1f80, 0x1f87},
    {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4},
    {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x2146, 0x2149},
    {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25}, {0xa72f, 0xa731},
    {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xab60, 0xab65},
    {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a}
#if CHRBITS > 16
    ,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df},
    {0x16e60, 0x16e7f}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467},
    {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf},
    {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f},
    {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f},
    {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714},
    {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788},


    {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943}
#endif
};

#define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange))

static const chr lowerCharTable[] = {
    0xb5, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10b, 0x10d, 0x10f,
    0x111, 0x113, 0x115, 0x117, 0x119, 0x11b, 0x11d, 0x11f, 0x121,
    0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133,
    0x135, 0x137, 0x138, 0x13a, 0x13c, 0x13e, 0x140, 0x142, 0x144,
    0x146, 0x148, 0x149, 0x14b, 0x14d, 0x14f, 0x151, 0x153, 0x155,
    0x157, 0x159, 0x15b, 0x15d, 0x15f, 0x161, 0x163, 0x165, 0x167,
    0x169, 0x16b, 0x16d, 0x16f, 0x171, 0x173, 0x175, 0x177, 0x17a,
    0x17c, 0x183, 0x185, 0x188, 0x18c, 0x18d, 0x192, 0x195, 0x19e,
    0x1a1, 0x1a3, 0x1a5, 0x1a8, 0x1aa, 0x1ab, 0x1ad, 0x1b0, 0x1b4,
    0x1b6, 0x1b9, 0x1ba, 0x1c6, 0x1c9, 0x1cc, 0x1ce, 0x1d0, 0x1d2,
    0x1d4, 0x1d6, 0x1d8, 0x1da, 0x1dc, 0x1dd, 0x1df, 0x1e1, 0x1e3,
    0x1e5, 0x1e7, 0x1e9, 0x1eb, 0x1ed, 0x1ef, 0x1f0, 0x1f3, 0x1f5,
    0x1f9, 0x1fb, 0x1fd, 0x1ff, 0x201, 0x203, 0x205, 0x207, 0x209,
    0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b,
    0x21d, 0x21f, 0x221, 0x223, 0x225, 0x227, 0x229, 0x22b, 0x22d,
    0x22f, 0x231, 0x23c, 0x23f, 0x240, 0x242, 0x247, 0x249, 0x24b,
    0x24d, 0x371, 0x373, 0x377, 0x390, 0x3d0, 0x3d1, 0x3d9, 0x3db,
    0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e5, 0x3e7, 0x3e9, 0x3eb, 0x3ed,
    0x3f5, 0x3f8, 0x3fb, 0x3fc, 0x461, 0x463, 0x465, 0x467, 0x469,
    0x46b, 0x46d, 0x46f, 0x471, 0x473, 0x475, 0x477, 0x479, 0x47b,
    0x47d, 0x47f, 0x481, 0x48b, 0x48d, 0x48f, 0x491, 0x493, 0x495,
    0x497, 0x499, 0x49b, 0x49d, 0x49f, 0x4a1, 0x4a3, 0x4a5, 0x4a7,
    0x4a9, 0x4ab, 0x4ad, 0x4af, 0x4b1, 0x4b3, 0x4b5, 0x4b7, 0x4b9,
    0x4bb, 0x4bd, 0x4bf, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4cc,
    0x4ce, 0x4cf, 0x4d1, 0x4d3, 0x4d5, 0x4d7, 0x4d9, 0x4db, 0x4dd,
    0x4df, 0x4e1, 0x4e3, 0x4e5, 0x4e7, 0x4e9, 0x4eb, 0x4ed, 0x4ef,
    0x4f1, 0x4f3, 0x4f5, 0x4f7, 0x4f9, 0x4fb, 0x4fd, 0x4ff, 0x501,
    0x503, 0x505, 0x507, 0x509, 0x50b, 0x50d, 0x50f, 0x511, 0x513,
    0x515, 0x517, 0x519, 0x51b, 0x51d, 0x51f, 0x521, 0x523, 0x525,
    0x527, 0x529, 0x52b, 0x52d, 0x52f, 0x1e01, 0x1e03, 0x1e05, 0x1e07,
    0x1e09, 0x1e0b, 0x1e0d, 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19,
    0x1e1b, 0x1e1d, 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b,
    0x1e2d, 0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d,
    0x1e3f, 0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d, 0x1e4f,
    0x1e51, 0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d, 0x1e5f, 0x1e61,
    0x1e63, 0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, 0x1e73,
    0x1e75, 0x1e77, 0x1e79, 0x1e7b, 0x1e7d, 0x1e7f, 0x1e81, 0x1e83, 0x1e85,
    0x1e87, 0x1e89, 0x1e8b, 0x1e8d, 0x1e8f, 0x1e91, 0x1e93, 0x1e9f, 0x1ea1,
    0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9, 0x1eab, 0x1ead, 0x1eaf, 0x1eb1, 0x1eb3,
    0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb, 0x1ebd, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5,
    0x1ec7, 0x1ec9, 0x1ecb, 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7,
    0x1ed9, 0x1edb, 0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9,
    0x1eeb, 0x1eed, 0x1eef, 0x1ef1, 0x1ef3, 0x1ef5, 0x1ef7, 0x1ef9, 0x1efb,
    0x1efd, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6,
    0x1ff7, 0x210a, 0x210e, 0x210f, 0x2113, 0x212f, 0x2134, 0x2139, 0x213c,
    0x213d, 0x214e, 0x2184, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c6a, 0x2c6c,
    0x2c71, 0x2c73, 0x2c74, 0x2c81, 0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b,
    0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97, 0x2c99, 0x2c9b, 0x2c9d,
    0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7, 0x2ca9, 0x2cab, 0x2cad, 0x2caf,
    0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7, 0x2cb9, 0x2cbb, 0x2cbd, 0x2cbf, 0x2cc1,
    0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9, 0x2ccb, 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3,
    0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb, 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce4,
    0x2cec, 0x2cee, 0x2cf3, 0x2d27, 0x2d2d, 0xa641, 0xa643, 0xa645, 0xa647,
    0xa649, 0xa64b, 0xa64d, 0xa64f, 0xa651, 0xa653, 0xa655, 0xa657, 0xa659,
    0xa65b, 0xa65d, 0xa65f, 0xa661, 0xa663, 0xa665, 0xa667, 0xa669, 0xa66b,
    0xa66d, 0xa681, 0xa683, 0xa685, 0xa687, 0xa689, 0xa68b, 0xa68d, 0xa68f,
    0xa691, 0xa693, 0xa695, 0xa697, 0xa699, 0xa69b, 0xa723, 0xa725, 0xa727,
    0xa729, 0xa72b, 0xa72d, 0xa733, 0xa735, 0xa737, 0xa739, 0xa73b, 0xa73d,
    0xa73f, 0xa741, 0xa743, 0xa745, 0xa747, 0xa749, 0xa74b, 0xa74d, 0xa74f,
    0xa751, 0xa753, 0xa755, 0xa757, 0xa759, 0xa75b, 0xa75d, 0xa75f, 0xa761,
    0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d, 0xa76f, 0xa77a, 0xa77c,
    0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797,
    0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9,
    0xa7af, 0xa7b5, 0xa7b7, 0xa7b9, 0xa7fa

#if CHRBITS > 16
    ,0x1d4bb, 0x1d7cb
#endif
};

#define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr))

/*
 * Unicode: uppercase characters.
 */

static const crange upperRangeTable[] = {
    {0x41, 0x5a}, {0xc0, 0xd6}, {0xd8, 0xde}, {0x189, 0x18b},
    {0x18e, 0x191}, {0x196, 0x198}, {0x1b1, 0x1b3}, {0x1f6, 0x1f8},
    {0x243, 0x246}, {0x388, 0x38a}, {0x391, 0x3a1}, {0x3a3, 0x3ab},
    {0x3d2, 0x3d4}, {0x3fd, 0x42f}, {0x531, 0x556}, {0x10a0, 0x10c5},
    {0x13a0, 0x13f5}, {0x1c90, 0x1cba}, {0x1cbd, 0x1cbf}, {0x1f08, 0x1f0f},
    {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d},
    {0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb}, {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb},
    {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, {0x210b, 0x210d}, {0x2110, 0x2112},
    {0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133}, {0x2c00, 0x2c2e},
    {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae},
    {0xa7b0, 0xa7b4}, {0xff21, 0xff3a}
#if CHRBITS > 16
    ,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf},
    {0x16e40, 0x16e5f}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481},
    {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a},
    {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544},
    {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed},
    {0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0},
    {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8},
    {0x1e900, 0x1e921}
#endif
};

#define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange))

static const chr upperCharTable[] = {
    0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x110,
    0x112, 0x114, 0x116, 0x118, 0x11a, 0x11c, 0x11e, 0x120, 0x122,
    0x124, 0x126, 0x128, 0x12a, 0x12c, 0x12e, 0x130, 0x132, 0x134,
    0x136, 0x139, 0x13b, 0x13d, 0x13f, 0x141, 0x143, 0x145, 0x147,
    0x14a, 0x14c, 0x14e, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15a,
    0x15c, 0x15e, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16a, 0x16c,
    0x16e, 0x170, 0x172, 0x174, 0x176, 0x178, 0x179, 0x17b, 0x17d,
    0x181, 0x182, 0x184, 0x186, 0x187, 0x193, 0x194, 0x19c, 0x19d,
    0x19f, 0x1a0, 0x1a2, 0x1a4, 0x1a6, 0x1a7, 0x1a9, 0x1ac, 0x1ae,
    0x1af, 0x1b5, 0x1b7, 0x1b8, 0x1bc, 0x1c4, 0x1c7, 0x1ca, 0x1cd,
    0x1cf, 0x1d1, 0x1d3, 0x1d5, 0x1d7, 0x1d9, 0x1db, 0x1de, 0x1e0,
    0x1e2, 0x1e4, 0x1e6, 0x1e8, 0x1ea, 0x1ec, 0x1ee, 0x1f1, 0x1f4,
    0x1fa, 0x1fc, 0x1fe, 0x200, 0x202, 0x204, 0x206, 0x208, 0x20a,
    0x20c, 0x20e, 0x210, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21c,
    0x21e, 0x220, 0x222, 0x224, 0x226, 0x228, 0x22a, 0x22c, 0x22e,
    0x230, 0x232, 0x23a, 0x23b, 0x23d, 0x23e, 0x241, 0x248, 0x24a,
    0x24c, 0x24e, 0x370, 0x372, 0x376, 0x37f, 0x386, 0x38c, 0x38e,
    0x38f, 0x3cf, 0x3d8, 0x3da, 0x3dc, 0x3de, 0x3e0, 0x3e2, 0x3e4,
    0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ee, 0x3f4, 0x3f7, 0x3f9, 0x3fa,
    0x460, 0x462, 0x464, 0x466, 0x468, 0x46a, 0x46c, 0x46e, 0x470,
    0x472, 0x474, 0x476, 0x478, 0x47a, 0x47c, 0x47e, 0x480, 0x48a,
    0x48c, 0x48e, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49a, 0x49c,
    0x49e, 0x4a0, 0x4a2, 0x4a4, 0x4a6, 0x4a8, 0x4aa, 0x4ac, 0x4ae,
    0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba, 0x4bc, 0x4be, 0x4c0,
    0x4c1, 0x4c3, 0x4c5, 0x4c7, 0x4c9, 0x4cb, 0x4cd, 0x4d0, 0x4d2,
    0x4d4, 0x4d6, 0x4d8, 0x4da, 0x4dc, 0x4de, 0x4e0, 0x4e2, 0x4e4,
    0x4e6, 0x4e8, 0x4ea, 0x4ec, 0x4ee, 0x4f0, 0x4f2, 0x4f4, 0x4f6,
    0x4f8, 0x4fa, 0x4fc, 0x4fe, 0x500, 0x502, 0x504, 0x506, 0x508,
    0x50a, 0x50c, 0x50e, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51a,
    0x51c, 0x51e, 0x520, 0x522, 0x524, 0x526, 0x528, 0x52a, 0x52c,
    0x52e, 0x10c7, 0x10cd, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a,
    0x1e0c, 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c,
    0x1e1e, 0x1e20, 0x1e22, 0x1e24, 0x1e26, 0x1e28, 0x1e2a, 0x1e2c, 0x1e2e,
    0x1e30, 0x1e32, 0x1e34, 0x1e36, 0x1e38, 0x1e3a, 0x1e3c, 0x1e3e, 0x1e40,
    0x1e42, 0x1e44, 0x1e46, 0x1e48, 0x1e4a, 0x1e4c, 0x1e4e, 0x1e50, 0x1e52,
    0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c, 0x1e5e, 0x1e60, 0x1e62, 0x1e64,
    0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, 0x1e72, 0x1e74, 0x1e76,
    0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80, 0x1e82, 0x1e84, 0x1e86, 0x1e88,
    0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92, 0x1e94, 0x1e9e, 0x1ea0, 0x1ea2,
    0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac, 0x1eae, 0x1eb0, 0x1eb2, 0x1eb4,
    0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6,
    0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0, 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8,
    0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2, 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea,
    0x1eec, 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4, 0x1ef6, 0x1ef8, 0x1efa, 0x1efc,
    0x1efe, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f, 0x2102, 0x2107, 0x2115, 0x2124,
    0x2126, 0x2128, 0x213e, 0x213f, 0x2145, 0x2183, 0x2c60, 0x2c67, 0x2c69,
    0x2c6b, 0x2c72, 0x2c75, 0x2c82, 0x2c84, 0x2c86, 0x2c88, 0x2c8a, 0x2c8c,
    0x2c8e, 0x2c90, 0x2c92, 0x2c94, 0x2c96, 0x2c98, 0x2c9a, 0x2c9c, 0x2c9e,
    0x2ca0, 0x2ca2, 0x2ca4, 0x2ca6, 0x2ca8, 0x2caa, 0x2cac, 0x2cae, 0x2cb0,
    0x2cb2, 0x2cb4, 0x2cb6, 0x2cb8, 0x2cba, 0x2cbc, 0x2cbe, 0x2cc0, 0x2cc2,
    0x2cc4, 0x2cc6, 0x2cc8, 0x2cca, 0x2ccc, 0x2cce, 0x2cd0, 0x2cd2, 0x2cd4,
    0x2cd6, 0x2cd8, 0x2cda, 0x2cdc, 0x2cde, 0x2ce0, 0x2ce2, 0x2ceb, 0x2ced,
    0x2cf2, 0xa640, 0xa642, 0xa644, 0xa646, 0xa648, 0xa64a, 0xa64c, 0xa64e,
    0xa650, 0xa652, 0xa654, 0xa656, 0xa658, 0xa65a, 0xa65c, 0xa65e, 0xa660,
    0xa662, 0xa664, 0xa666, 0xa668, 0xa66a, 0xa66c, 0xa680, 0xa682, 0xa684,
    0xa686, 0xa688, 0xa68a, 0xa68c, 0xa68e, 0xa690, 0xa692, 0xa694, 0xa696,
    0xa698, 0xa69a, 0xa722, 0xa724, 0xa726, 0xa728, 0xa72a, 0xa72c, 0xa72e,
    0xa732, 0xa734, 0xa736, 0xa738, 0xa73a, 0xa73c, 0xa73e, 0xa740, 0xa742,
    0xa744, 0xa746, 0xa748, 0xa74a, 0xa74c, 0xa74e, 0xa750, 0xa752, 0xa754,
    0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762, 0xa764, 0xa766,
    0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780,
    0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798,
    0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6,

    0xa7b8
#if CHRBITS > 16
    ,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538,
    0x1d539, 0x1d546, 0x1d7ca
#endif
};

#define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr))

/*
 * Unicode: unicode print characters excluding space.
 */

static const crange graphRangeTable[] = {
    {0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37f},
    {0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x52f}, {0x531, 0x556},
    {0x559, 0x58a}, {0x58d, 0x58f}, {0x591, 0x5c7}, {0x5d0, 0x5ea},
    {0x5ef, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, {0x6de, 0x70d},
    {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, {0x7fd, 0x82d},
    {0x830, 0x83e}, {0x840, 0x85b}, {0x860, 0x86a}, {0x8a0, 0x8b4},
    {0x8b6, 0x8bd}, {0x8d3, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c},
    {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4},
    {0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fe}, {0xa01, 0xa03},
    {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42},
    {0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa76}, {0xa81, 0xa83},
    {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0},
    {0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd},
    {0xae0, 0xae3}, {0xae6, 0xaf1}, {0xaf9, 0xaff}, {0xb01, 0xb03},
    {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39},
    {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77},
    {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa},
    {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd},
    {0xbe6, 0xbfa}, {0xc00, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28},
    {0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d},
    {0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc8c},
    {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9},
    {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3},
    {0xce6, 0xcef}, {0xd00, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10},
    {0xd12, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4f}, {0xd54, 0xd63},
    {0xd66, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb},
    {0xdc0, 0xdc6}, {0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef},
    {0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97},
    {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd},
    {0xec0, 0xec4}, {0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf},
    {0xf00, 0xf47}, {0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc},
    {0xfbe, 0xfcc}, {0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248},
    {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288},
    {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be},
    {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315},
    {0x1318, 0x135a}, {0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5},
    {0x13f8, 0x13fd}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8},
    {0x1700, 0x170c}, {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753},
    {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9},
    {0x17f0, 0x17f9}, {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1878},
    {0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b},
    {0x1930, 0x193b}, {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab},
    {0x19b0, 0x19c9}, {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e},
    {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad},
    {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3},
    {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49}, {0x1c4d, 0x1c88}, {0x1c90, 0x1cba},
    {0x1cbd, 0x1cc7}, {0x1cd0, 0x1cf9}, {0x1d00, 0x1df9}, {0x1dfb, 0x1f15},
    {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57},
    {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3},
    {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe},
    {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e}, {0x2090, 0x209c},
    {0x20a0, 0x20bf}, {0x20d0, 0x20f0}, {0x2100, 0x218b}, {0x2190, 0x2426},
    {0x2440, 0x244a}, {0x2460, 0x2b73}, {0x2b76, 0x2b95}, {0x2b98, 0x2bc8},
    {0x2bca, 0x2bfe}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3},
    {0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6},
    {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6},
    {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e4e},
    {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb},
    {0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312f},
    {0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e},
    {0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fef}, {0xa000, 0xa48c},
    {0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7b9},
    {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877}, {0xa880, 0xa8c5},
    {0xa8ce, 0xa8d9}, {0xa8e0, 0xa953}, {0xa95f, 0xa97c}, {0xa980, 0xa9cd},
    {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, {0xaa00, 0xaa36}, {0xaa40, 0xaa4d},
    {0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, {0xaadb, 0xaaf6}, {0xab01, 0xab06},
    {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e},
    {0xab30, 0xab65}, {0xab70, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3},
    {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9},
    {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c},
    {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7},
    {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe52}, {0xfe54, 0xfe66},
    {0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe},
    {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc},
    {0xffe0, 0xffe6}, {0xffe8, 0xffee}
#if CHRBITS > 16
    ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d},
    {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133},
    {0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c},
    {0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x1032d, 0x1034a},
    {0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5},
    {0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x104b0, 0x104d3}, {0x104d8, 0x104fb},
    {0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},


    {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855},
    {0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b},
    {0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03},
    {0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a38, 0x10a3a},
    {0x10a3f, 0x10a48}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6},
    {0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72},
    {0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48},
    {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10d27}, {0x10d30, 0x10d39},

    {0x10e60, 0x10e7e}, {0x10f00, 0x10f27}, {0x10f30, 0x10f59}, {0x11000, 0x1104d},
    {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8},
    {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11146}, {0x11150, 0x11176},
    {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211},
    {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d},
    {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303},
    {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339},
    {0x1133b, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c},
    {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7}, {0x114d0, 0x114d9},

    {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644}, {0x11650, 0x11659},
    {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x11700, 0x1171a},
    {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x11800, 0x1183b}, {0x118a0, 0x118f2},

    {0x11a00, 0x11a47}, {0x11a50, 0x11a83}, {0x11a86, 0x11aa2}, {0x11ac0, 0x11af8},

    {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45}, {0x11c50, 0x11c6c},
    {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6}, {0x11d00, 0x11d06},
    {0x11d0b, 0x11d36}, {0x11d3f, 0x11d47}, {0x11d50, 0x11d59}, {0x11d60, 0x11d65},
    {0x11d6a, 0x11d8e}, {0x11d93, 0x11d98}, {0x11da0, 0x11da9}, {0x11ee0, 0x11ef8},

    {0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543},
    {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e},
    {0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45},
    {0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f},
    {0x16e40, 0x16e9a}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f},
    {0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb},
    {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99},
    {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172},
    {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d2e0, 0x1d2f3}, {0x1d300, 0x1d356},
    {0x1d360, 0x1d378}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac},
    {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a},
    {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e},
    {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb},
    {0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006},
    {0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4},
    {0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ec71, 0x1ecb4},
    {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37},
    {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77},
    {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3},
    {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093},
    {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5},
    {0x1f100, 0x1f10c}, {0x1f110, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202},






    {0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4},

    {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f9}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d8},
    {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887},
    {0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b}, {0x1f910, 0x1f93e}, {0x1f940, 0x1f970},

    {0x1f973, 0x1f976}, {0x1f97c, 0x1f9a2}, {0x1f9b0, 0x1f9b9}, {0x1f9c0, 0x1f9c2},
    {0x1f9d0, 0x1f9ff}, {0x1fa60, 0x1fa6d}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734},

    {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d},
    {0xe0100, 0xe01ef}
#endif
};

#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))

static const chr graphCharTable[] = {
    0x38c, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8, 0x9d7, 0x9dc,
    0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39,
    0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3, 0xad0, 0xb0f,
    0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57, 0xb5c, 0xb5d,
    0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4,
    0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde, 0xcf1, 0xcf2,
    0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82, 0xe84, 0xe87,
    0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xec6, 0x10c7,
    0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59, 0x1f5b, 0x1f5d,

    0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41,
    0xfb43, 0xfb44, 0xfffc, 0xfffd
#if CHRBITS > 16
    ,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4,
    0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333,
    0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x1145e, 0x118ff, 0x11d08,

    0x11d09, 0x11d3a, 0x11d3c, 0x11d3d, 0x11d67, 0x11d68, 0x11d90, 0x11d91, 0x16a6e,
    0x16a6f, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb,
    0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27,
    0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54,
    0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e,

    0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f97a
#endif
};

#define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr))

/*
 *	End of auto-generated Unicode character ranges declarations.
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
		addchr(cv, alphaCharTable[i]);
	    }
	}
	break;
    case CC_ASCII:
	cv = getcvec(v, 0, 1);
	if (cv) {
	    addrange(cv, 0, 0x7F);
	}
	break;
    case CC_BLANK:
	cv = getcvec(v, 2, 0);
	addchr(cv, '\t');
	addchr(cv, ' ');
	break;







|







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
		addchr(cv, alphaCharTable[i]);
	    }
	}
	break;
    case CC_ASCII:
	cv = getcvec(v, 0, 1);
	if (cv) {
	    addrange(cv, 0, 0x7f);
	}
	break;
    case CC_BLANK:
	cv = getcvec(v, 2, 0);
	addchr(cv, '\t');
	addchr(cv, ' ');
	break;

Changes to generic/regcomp.c.

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
    for (a=pre->outs ; a!=NULL ; a=a->outchain) {
	s = a->to;
	for (b=s->ins ; b!=NULL ; b=b->inchain) {
	    if (b->from != pre) {
		break;
	    }
	}

	/*
	 * We want to mark states as being in the list already by having non
	 * NULL tmp fields, but we can't just store the old slist value in tmp
	 * because that doesn't work for the first such state.  Instead, the
	 * first list entry gets its own address in tmp.
	 */
	if (b != NULL && s->tmp == NULL) {







|







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
    for (a=pre->outs ; a!=NULL ; a=a->outchain) {
	s = a->to;
	for (b=s->ins ; b!=NULL ; b=b->inchain) {
	    if (b->from != pre) {
		break;
	    }
	}
 
	/*
	 * We want to mark states as being in the list already by having non
	 * NULL tmp fields, but we can't just store the old slist value in tmp
	 * because that doesn't work for the first such state.  Instead, the
	 * first list entry gets its own address in tmp.
	 */
	if (b != NULL && s->tmp == NULL) {
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
	}

	/*
	 * Legal in EREs due to specification botch.
	 */

	NOTE(REG_UPBOTCH);
	/* FALLTHRU */
    case PLAIN:
	onechr(v, v->nextvalue, lp, rp);
	okcolors(v->nfa, v->cm);
	NOERR();
	NEXT();
	break;
    case '[':







|







918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
	}

	/*
	 * Legal in EREs due to specification botch.
	 */

	NOTE(REG_UPBOTCH);
	/* fallthrough into case PLAIN */
    case PLAIN:
	onechr(v, v->nextvalue, lp, rp);
	okcolors(v->nfa, v->cm);
	NOERR();
	NEXT();
	break;
    case '[':

Changes to generic/regcustom.h.

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
typedef Tcl_UniChar chr;	/* The type itself. */
typedef int pchr;		/* What it promotes to. */
typedef unsigned uchr;		/* Unsigned type that will hold a chr. */
typedef int celt;		/* Type to hold chr, or NOCELT */
#define	NOCELT (-1)		/* Celt value which is not valid chr */
#define	CHR(c) (UCHAR(c))	/* Turn char literal into chr literal */
#define	DIGITVAL(c) ((c)-'0')	/* Turn chr digit into its value */
#if TCL_UTF_MAX > 3
#define	CHRBITS	32		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x00000000	/* Smallest and largest chr; the value */
#define	CHR_MAX	0xffffffff	/* CHR_MAX-CHR_MIN+1 should fit in uchr */
#else
#define	CHRBITS	16		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x0000		/* Smallest and largest chr; the value */
#define	CHR_MAX	0xffff		/* CHR_MAX-CHR_MIN+1 should fit in uchr */







|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
typedef Tcl_UniChar chr;	/* The type itself. */
typedef int pchr;		/* What it promotes to. */
typedef unsigned uchr;		/* Unsigned type that will hold a chr. */
typedef int celt;		/* Type to hold chr, or NOCELT */
#define	NOCELT (-1)		/* Celt value which is not valid chr */
#define	CHR(c) (UCHAR(c))	/* Turn char literal into chr literal */
#define	DIGITVAL(c) ((c)-'0')	/* Turn chr digit into its value */
#if TCL_UTF_MAX > 4
#define	CHRBITS	32		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x00000000	/* Smallest and largest chr; the value */
#define	CHR_MAX	0xffffffff	/* CHR_MAX-CHR_MIN+1 should fit in uchr */
#else
#define	CHRBITS	16		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x0000		/* Smallest and largest chr; the value */
#define	CHR_MAX	0xffff		/* CHR_MAX-CHR_MIN+1 should fit in uchr */

Changes to generic/tcl.decls.

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
# tcl.decls --
#
#	This file contains the declarations for all supported public
#	functions that are exported by the Tcl library via the stubs table.
#	This file is used to generate the tclDecls.h, tclPlatDecls.h
#	and tclStubInit.c files.
#
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2001, 2002 Kevin B. Kenny.  All rights reserved.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the tcl interface with several sub interfaces:
#     tclPlat	 - platform specific public
#     tclInt	 - generic private
#     tclPlatInt - platform specific private

interface tcl
hooks {tclPlat tclInt tclIntPlat}
scspec EXTERN

# Declare each of the functions in the public Tcl interface.  Note that
# the an index should never be reused for a different function in order
# to preserve backwards compatibility.

declare 0 {
    int Tcl_PkgProvideEx(Tcl_Interp *interp, const char *name,







|
|














<







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
# tcl.decls --
#
#	This file contains the declarations for all supported public
#	functions that are exported by the Tcl library via the stubs table.
#	This file is used to generate the tclDecls.h, tclPlatDecls.h
#	and tclStubInit.c files.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the tcl interface with several sub interfaces:
#     tclPlat	 - platform specific public
#     tclInt	 - generic private
#     tclPlatInt - platform specific private

interface tcl
hooks {tclPlat tclInt tclIntPlat}


# Declare each of the functions in the public Tcl interface.  Note that
# the an index should never be reused for a different function in order
# to preserve backwards compatibility.

declare 0 {
    int Tcl_PkgProvideEx(Tcl_Interp *interp, const char *name,
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
declare 29 {
    Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
declare 30 {
    void TclFreeObj(Tcl_Obj *objPtr)
}
declare 31 {
    int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *intPtr)
}
declare 32 {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *intPtr)
}
declare 33 {
    unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
declare 34 {
    int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr)
}







|



|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
declare 29 {
    Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
declare 30 {
    void TclFreeObj(Tcl_Obj *objPtr)
}
declare 31 {
    int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr)
}
declare 32 {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *boolPtr)
}
declare 33 {
    unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
declare 34 {
    int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr)
}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
	    int *lengthPtr)
}
declare 48 {
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first,
	    int count, int objc, Tcl_Obj *const objv[])
}
declare 49 {
    Tcl_Obj *Tcl_NewBooleanObj(int intValue)
}
declare 50 {
    Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, int length)
}
declare 51 {
    Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
}







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
	    int *lengthPtr)
}
declare 48 {
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first,
	    int count, int objc, Tcl_Obj *const objv[])
}
declare 49 {
    Tcl_Obj *Tcl_NewBooleanObj(int boolValue)
}
declare 50 {
    Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, int length)
}
declare 51 {
    Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
}
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
declare 55 {
    Tcl_Obj *Tcl_NewObj(void)
}
declare 56 {
    Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length)
}
declare 57 {
    void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int intValue)
}
declare 58 {
    unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int numBytes)
}
declare 59 {
    void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes,
	    int numBytes)
}
declare 60 {
    void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
}
declare 61 {
    void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue)
}







|


|



|







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
declare 55 {
    Tcl_Obj *Tcl_NewObj(void)
}
declare 56 {
    Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length)
}
declare 57 {
    void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue)
}
declare 58 {
    unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length)
}
declare 59 {
    void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes,
	    int length)
}
declare 60 {
    void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
}
declare 61 {
    void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue)
}
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
    int Tcl_ConvertElement(const char *src, char *dst, int flags)
}
declare 85 {
    int Tcl_ConvertCountedElement(const char *src, int length, char *dst,
	    int flags)
}
declare 86 {
    int Tcl_CreateAlias(Tcl_Interp *childInterp, const char *childCmd,
	    Tcl_Interp *target, const char *targetCmd, int argc,
	    CONST84 char *const *argv)
}
declare 87 {
    int Tcl_CreateAliasObj(Tcl_Interp *childInterp, const char *childCmd,
	    Tcl_Interp *target, const char *targetCmd, int objc,
	    Tcl_Obj *const objv[])
}
declare 88 {
    Tcl_Channel Tcl_CreateChannel(Tcl_ChannelType *typePtr,
	    const char *chanName, ClientData instanceData, int mask)
}







|




|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
    int Tcl_ConvertElement(const char *src, char *dst, int flags)
}
declare 85 {
    int Tcl_ConvertCountedElement(const char *src, int length, char *dst,
	    int flags)
}
declare 86 {
    int Tcl_CreateAlias(Tcl_Interp *slave, const char *slaveCmd,
	    Tcl_Interp *target, const char *targetCmd, int argc,
	    CONST84 char *const *argv)
}
declare 87 {
    int Tcl_CreateAliasObj(Tcl_Interp *slave, const char *slaveCmd,
	    Tcl_Interp *target, const char *targetCmd, int objc,
	    Tcl_Obj *const objv[])
}
declare 88 {
    Tcl_Channel Tcl_CreateChannel(Tcl_ChannelType *typePtr,
	    const char *chanName, ClientData instanceData, int mask)
}
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
declare 96 {
    Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp,
	    const char *cmdName,
	    Tcl_ObjCmdProc *proc, ClientData clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 97 {
    Tcl_Interp *Tcl_CreateSlave(Tcl_Interp *interp, const char *name,
	    int isSafe)
}
declare 98 {
    Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds,
	    Tcl_TimerProc *proc, ClientData clientData)
}
declare 99 {







|







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
declare 96 {
    Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp,
	    const char *cmdName,
	    Tcl_ObjCmdProc *proc, ClientData clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 97 {
    Tcl_Interp *Tcl_CreateSlave(Tcl_Interp *interp, const char *slaveName,
	    int isSafe)
}
declare 98 {
    Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds,
	    Tcl_TimerProc *proc, ClientData clientData)
}
declare 99 {
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
declare 161 {
    int Tcl_GetErrno(void)
}
declare 162 {
    CONST84_RETURN char *Tcl_GetHostName(void)
}
declare 163 {
    int Tcl_GetInterpPath(Tcl_Interp *interp, Tcl_Interp *childInterp)
}
declare 164 {
    Tcl_Interp *Tcl_GetMaster(Tcl_Interp *interp)
}
declare 165 {
    const char *Tcl_GetNameOfExecutable(void)
}







|







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
declare 161 {
    int Tcl_GetErrno(void)
}
declare 162 {
    CONST84_RETURN char *Tcl_GetHostName(void)
}
declare 163 {
    int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp)
}
declare 164 {
    Tcl_Interp *Tcl_GetMaster(Tcl_Interp *interp)
}
declare 165 {
    const char *Tcl_GetNameOfExecutable(void)
}
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# This is obsolete, use Tcl_FSOpenFileChannel
declare 198 {
    Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName,
	    const char *modeString, int permissions)
}
declare 199 {
    Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
	    const char *address, const char *myaddr, int myport, int flags)
}
declare 200 {
    Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
	    const char *host, Tcl_TcpAcceptProc *acceptProc,
	    ClientData callbackData)
}
declare 201 {







|







707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
# This is obsolete, use Tcl_FSOpenFileChannel
declare 198 {
    Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName,
	    const char *modeString, int permissions)
}
declare 199 {
    Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
	    const char *address, const char *myaddr, int myport, int async)
}
declare 200 {
    Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
	    const char *host, Tcl_TcpAcceptProc *acceptProc,
	    ClientData callbackData)
}
declare 201 {
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
    void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr,
	    Tcl_Time *timePtr)
}
declare 312 {
    int Tcl_NumUtfChars(const char *src, int length)
}
declare 313 {
    int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
	    int charsToRead, int appendFlag)
}
declare 314 {
    void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
}
declare 315 {
    void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
}







|
|







1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
    void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr,
	    Tcl_Time *timePtr)
}
declare 312 {
    int Tcl_NumUtfChars(const char *src, int length)
}
declare 313 {
    int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead,
	    int appendFlag)
}
declare 314 {
    void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
}
declare 315 {
    void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
}
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
    void Tcl_FreeParse(Tcl_Parse *parsePtr)
}
declare 359 {
    void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script,
	    const char *command, int length)
}
declare 360 {
    int Tcl_ParseBraces(Tcl_Interp *interp, const char *start,
	    int numBytes, Tcl_Parse *parsePtr, int append,
	    CONST84 char **termPtr)
}
declare 361 {
    int Tcl_ParseCommand(Tcl_Interp *interp, const char *start,
	    int numBytes, int nested, Tcl_Parse *parsePtr)
}
declare 362 {
    int Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
	    int numBytes, Tcl_Parse *parsePtr)
}
declare 363 {
    int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
	    int numBytes, Tcl_Parse *parsePtr, int append,
	    CONST84 char **termPtr)
}
declare 364 {
    int Tcl_ParseVarName(Tcl_Interp *interp, const char *start,
	    int numBytes, Tcl_Parse *parsePtr, int append)
}
# These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir,
# Tcl_FSAccess and Tcl_FSStat
declare 365 {
    char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
declare 366 {







|
|
<


|
|


|
|







|
|







1272
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
    void Tcl_FreeParse(Tcl_Parse *parsePtr)
}
declare 359 {
    void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script,
	    const char *command, int length)
}
declare 360 {
    int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, int numBytes,
	    Tcl_Parse *parsePtr, int append, CONST84 char **termPtr)

}
declare 361 {
    int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, int numBytes,
	    int nested, Tcl_Parse *parsePtr)
}
declare 362 {
    int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, int numBytes,
	    Tcl_Parse *parsePtr)
}
declare 363 {
    int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
	    int numBytes, Tcl_Parse *parsePtr, int append,
	    CONST84 char **termPtr)
}
declare 364 {
    int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, int numBytes,
	    Tcl_Parse *parsePtr, int append)
}
# These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir,
# Tcl_FSAccess and Tcl_FSStat
declare 365 {
    char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
declare 366 {
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
}

# TIP#270 (utility C routines for string formatting) dgp
declare 574 {
    void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr)
}
declare 575 {
    void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes,
	    int length, int limit, const char *ellipsis)
}
declare 576 {
    Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int objc,
	    Tcl_Obj *const objv[])
}
declare 577 {
    int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    const char *format, int objc, Tcl_Obj *const objv[])
}
declare 578 {
    Tcl_Obj *Tcl_ObjPrintf(const char *format, ...)
}
declare 579 {
    void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...)
}

# ----- BASELINE -- FOR -- 8.5.0 ----- #

declare 687 {
    void TclUnusedStubEntry(void)
}

# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- #

##############################################################################

# Define the platform specific public Tcl interface. These functions are only
# available on the designated platform.

interface tclPlat








|
|















<
<
<
|



<
<







2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109



2110
2111
2112
2113


2114
2115
2116
2117
2118
2119
2120
}

# TIP#270 (utility C routines for string formatting) dgp
declare 574 {
    void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr)
}
declare 575 {
    void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes, int length,
	    int limit, const char *ellipsis)
}
declare 576 {
    Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int objc,
	    Tcl_Obj *const objv[])
}
declare 577 {
    int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    const char *format, int objc, Tcl_Obj *const objv[])
}
declare 578 {
    Tcl_Obj *Tcl_ObjPrintf(const char *format, ...)
}
declare 579 {
    void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...)
}



declare 630 {
    void TclUnusedStubEntry(void)
}



##############################################################################

# Define the platform specific public Tcl interface. These functions are only
# available on the designated platform.

interface tclPlat

2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169

declare 0 win {
    TCHAR *Tcl_WinUtfToTChar(const char *str, int len, Tcl_DString *dsPtr)
}
declare 1 win {
    char *Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr)
}
declare 3 win {
    void TclUnusedStubEntry(void)
}

################################
# Mac OS X specific functions

declare 0 macosx {
    int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
	    const char *bundleName, int hasResourceFile,
	    int maxPathLen, char *libraryPath)
}
declare 1 macosx {
    int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp,
	    const char *bundleName, const char *bundleVersion,
	    int hasResourceFile, int maxPathLen, char *libraryPath)
}
declare 2 macosx {
    void TclUnusedStubEntry(void)
}

##############################################################################

# Public functions that are not accessible via the stubs table.

export {
    void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc)







<
<
<














<
<
<







2129
2130
2131
2132
2133
2134
2135



2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149



2150
2151
2152
2153
2154
2155
2156

declare 0 win {
    TCHAR *Tcl_WinUtfToTChar(const char *str, int len, Tcl_DString *dsPtr)
}
declare 1 win {
    char *Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr)
}




################################
# Mac OS X specific functions

declare 0 macosx {
    int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
	    const char *bundleName, int hasResourceFile,
	    int maxPathLen, char *libraryPath)
}
declare 1 macosx {
    int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp,
	    const char *bundleName, const char *bundleVersion,
	    int hasResourceFile, int maxPathLen, char *libraryPath)
}




##############################################################################

# Public functions that are not accessible via the stubs table.

export {
    void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc)
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
}
export {
    TclIntPlatStubs *tclIntPlatStubsPtr         (fool checkstubs)
}
export {
    TclTomMathStubs *tclTomMathStubsPtr         (fool checkstubs)
}

# Local Variables:
# mode: tcl
# End:







<



2184
2185
2186
2187
2188
2189
2190

2191
2192
2193
}
export {
    TclIntPlatStubs *tclIntPlatStubsPtr         (fool checkstubs)
}
export {
    TclTomMathStubs *tclTomMathStubsPtr         (fool checkstubs)
}

# Local Variables:
# mode: tcl
# End:

Changes to generic/tcl.h.

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#	define TCL_WIDE_INT_TYPE long long
#	undef TCL_WIDE_INT_IS_LONG
#	undef TCL_CFG_DO64BIT
#    endif /* __LP64__ */
#    undef HAVE_STRUCT_STAT64
#endif /* __APPLE__ */

/* Cross-compiling 32-bit on a 64-bit platform? Then our
 * configure script does the wrong thing. Correct that here.
 */
#if defined(__GNUC__) && !defined(_WIN32) && !defined(__LP64__)
#   undef TCL_WIDE_INT_IS_LONG
#   undef TCL_WIDE_INT_TYPE
#   define TCL_WIDE_INT_TYPE long long
#endif

/*
 * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define
 * Tcl_WideUInt to be the unsigned variant of that type (assuming that where
 * we have one, we can have the other.)
 *
 * Also defines the following macros:
 * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a real







<
<
<
<
<
<
<
<
<







328
329
330
331
332
333
334









335
336
337
338
339
340
341
#	define TCL_WIDE_INT_TYPE long long
#	undef TCL_WIDE_INT_IS_LONG
#	undef TCL_CFG_DO64BIT
#    endif /* __LP64__ */
#    undef HAVE_STRUCT_STAT64
#endif /* __APPLE__ */










/*
 * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define
 * Tcl_WideUInt to be the unsigned variant of that type (assuming that where
 * we have one, we can have the other.)
 *
 * Also defines the following macros:
 * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a real
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
 *
 * Note on converting between Tcl_WideInt and strings. This implementation (in
 * tclObj.c) depends on the function
 * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
 */

#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
#   if defined(__WIN32__) && (!defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO)
#      define TCL_WIDE_INT_TYPE __int64
#      ifdef __BORLANDC__
#         define TCL_LL_MODIFIER	"L"
#      else /* __BORLANDC__ */
#         define TCL_LL_MODIFIER	"I64"
#      endif /* __BORLANDC__ */
#   elif defined(__GNUC__)







|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
 *
 * Note on converting between Tcl_WideInt and strings. This implementation (in
 * tclObj.c) depends on the function
 * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
 */

#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
#   if defined(__WIN32__)
#      define TCL_WIDE_INT_TYPE __int64
#      ifdef __BORLANDC__
#         define TCL_LL_MODIFIER	"L"
#      else /* __BORLANDC__ */
#         define TCL_LL_MODIFIER	"I64"
#      endif /* __BORLANDC__ */
#   elif defined(__GNUC__)
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#   define Tcl_WideAsDouble(val)	((double)((Tcl_WideInt)(val)))
#   define Tcl_DoubleAsWide(val)	((Tcl_WideInt)((double)(val)))
#endif /* TCL_WIDE_INT_IS_LONG */

#if defined(__WIN32__)
#   ifdef __BORLANDC__
	typedef struct stati64 Tcl_StatBuf;
#   elif defined(_WIN64) || defined(_USE_64BIT_TIME_T)
	typedef struct __stat64 Tcl_StatBuf;
#   elif (defined(_MSC_VER) && (_MSC_VER < 1400)) || defined(_USE_32BIT_TIME_T)
	typedef struct _stati64	Tcl_StatBuf;
#   else
	typedef struct _stat32i64 Tcl_StatBuf;
#   endif /* _MSC_VER < 1400 */
#elif defined(__CYGWIN__)







|







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
#   define Tcl_WideAsDouble(val)	((double)((Tcl_WideInt)(val)))
#   define Tcl_DoubleAsWide(val)	((Tcl_WideInt)((double)(val)))
#endif /* TCL_WIDE_INT_IS_LONG */

#if defined(__WIN32__)
#   ifdef __BORLANDC__
	typedef struct stati64 Tcl_StatBuf;
#   elif defined(_WIN64)
	typedef struct __stat64 Tcl_StatBuf;
#   elif (defined(_MSC_VER) && (_MSC_VER < 1400)) || defined(_USE_32BIT_TIME_T)
	typedef struct _stati64	Tcl_StatBuf;
#   else
	typedef struct _stat32i64 Tcl_StatBuf;
#   endif /* _MSC_VER < 1400 */
#elif defined(__CYGWIN__)
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
 *				the lower bits. If this flag is set then the
 *				hash table will attempt to rectify this by
 *				randomising the bits and then using the upper
 *				N bits as the index into the table.
 * TCL_HASH_KEY_SYSTEM_HASH -	If this flag is set then all memory internally
 *                              allocated for the hash table that is not for an
 *                              entry will use the system heap.
 * TCL_HASH_KEY_DIRECT_COMPARE -
 * 	                        Allows fast comparison for hash keys directly
 *                              by compare of their key.oneWordValue values,
 *                              before call of compareKeysProc (much slower
 *                              than a direct compare, so it is speed-up only
 *                              flag). Don't use it if keys contain values rather
 *                              than pointers.
 */

#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
#define TCL_HASH_KEY_SYSTEM_HASH    0x2
#define TCL_HASH_KEY_DIRECT_COMPARE 0x4

/*
 * Structure definition for the methods associated with a hash table key type.
 */

#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {







<
<
<
<
<
<
<




<







1149
1150
1151
1152
1153
1154
1155







1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
 *				the lower bits. If this flag is set then the
 *				hash table will attempt to rectify this by
 *				randomising the bits and then using the upper
 *				N bits as the index into the table.
 * TCL_HASH_KEY_SYSTEM_HASH -	If this flag is set then all memory internally
 *                              allocated for the hash table that is not for an
 *                              entry will use the system heap.







 */

#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
#define TCL_HASH_KEY_SYSTEM_HASH    0x2


/*
 * Structure definition for the methods associated with a hash table key type.
 */

#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170

2171

2172
2173
2174
2175
2176
2177
2178
#endif

/*
 * This represents a Unicode character. Any changes to this should also be
 * reflected in regcustom.h.
 */

#if TCL_UTF_MAX > 3
    /*
     * unsigned int isn't 100% accurate as it should be a strict 4-byte value.

     * The size of this value must be reflected correctly in regcustom.h.

     * XXX: Tcl is currently UCS-2 and planning UTF-16 for the Unicode
     * XXX: string rep that Tcl_UniChar represents.  Changing the size
     * XXX: of Tcl_UniChar is /not/ supported.
     */
typedef unsigned int Tcl_UniChar;
#else
typedef unsigned short Tcl_UniChar;







|

|
>
|
>







2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
#endif

/*
 * This represents a Unicode character. Any changes to this should also be
 * reflected in regcustom.h.
 */

#if TCL_UTF_MAX > 4
    /*
     * unsigned int isn't 100% accurate as it should be a strict 4-byte value
     * (perhaps wchar_t). 64-bit systems may have troubles. The size of this
     * value must be reflected correctly in regcustom.h and
     * in tclEncoding.c.
     * XXX: Tcl is currently UCS-2 and planning UTF-16 for the Unicode
     * XXX: string rep that Tcl_UniChar represents.  Changing the size
     * XXX: of Tcl_UniChar is /not/ supported.
     */
typedef unsigned int Tcl_UniChar;
#else
typedef unsigned short Tcl_UniChar;

Changes to generic/tclBasic.c.

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    {"pwd",		Tcl_PwdObjCmd,		NULL,			0},
    {"read",		Tcl_ReadObjCmd,		NULL,			1},
    {"seek",		Tcl_SeekObjCmd,		NULL,			1},
    {"socket",		Tcl_SocketObjCmd,	NULL,			0},
    {"source",		Tcl_SourceObjCmd,	NULL,			0},
    {"tell",		Tcl_TellObjCmd,		NULL,			1},
    {"time",		Tcl_TimeObjCmd,		NULL,			1},
#ifdef TCL_TIMERATE
    {"timerate",	Tcl_TimeRateObjCmd,	NULL,			1},
#endif
    {"unload",		Tcl_UnloadObjCmd,	NULL,			0},
    {"update",		Tcl_UpdateObjCmd,	NULL,			1},
    {"vwait",		Tcl_VwaitObjCmd,	NULL,			1},
    {NULL,		NULL,			NULL,			0}
};

/*







<
<
<







199
200
201
202
203
204
205



206
207
208
209
210
211
212
    {"pwd",		Tcl_PwdObjCmd,		NULL,			0},
    {"read",		Tcl_ReadObjCmd,		NULL,			1},
    {"seek",		Tcl_SeekObjCmd,		NULL,			1},
    {"socket",		Tcl_SocketObjCmd,	NULL,			0},
    {"source",		Tcl_SourceObjCmd,	NULL,			0},
    {"tell",		Tcl_TellObjCmd,		NULL,			1},
    {"time",		Tcl_TimeObjCmd,		NULL,			1},



    {"unload",		Tcl_UnloadObjCmd,	NULL,			0},
    {"update",		Tcl_UpdateObjCmd,	NULL,			1},
    {"vwait",		Tcl_VwaitObjCmd,	NULL,			1},
    {NULL,		NULL,			NULL,			0}
};

/*
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
{
    Interp *iPtr;
    Tcl_Interp *interp;
    Command *cmdPtr;
    const BuiltinFuncDef *builtinFuncPtr;
    const OpCmdInfo *opcmdInfoPtr;
    const CmdInfo *cmdInfoPtr;
    Tcl_Namespace *nsPtr;
    union {
	char c[sizeof(short)];
	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */







|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
{
    Interp *iPtr;
    Tcl_Interp *interp;
    Command *cmdPtr;
    const BuiltinFuncDef *builtinFuncPtr;
    const OpCmdInfo *opcmdInfoPtr;
    const CmdInfo *cmdInfoPtr;
    Tcl_Namespace *mathfuncNSPtr, *mathopNSPtr;
    union {
	char c[sizeof(short)];
	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */
409
410
411
412
413
414
415
416
417

418
419
420
421
422

423
424
425
426
427
428
429
     */

    if (sizeof(Tcl_CallFrame) < sizeof(CallFrame)) {
	/*NOTREACHED*/
	Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame");
    }

#if defined(_WIN32) && !defined(_WIN64) && !defined(_USE_64BIT_TIME_T)
    /* If Tcl is compiled on Win32 using -D_USE_64BIT_TIME_T

     * the result is a binary incompatible with the 'standard' build of
     * Tcl: All extensions using Tcl_StatBuf need to be recompiled in
     * the same way. Therefore, this is not officially supported.
     * In stead, it is recommended to use Win64 or Tcl 9.0 (not released yet)
     */

    if ((TclOffset(Tcl_StatBuf,st_atime) != 32)
	    || (TclOffset(Tcl_StatBuf,st_ctime) != 40)) {
	/*NOTREACHED*/
	Tcl_Panic("<sys/stat.h> is not compatible with MSVC");
    }
#endif








|
|
>
|
<
<
<
<
>







406
407
408
409
410
411
412
413
414
415
416




417
418
419
420
421
422
423
424
     */

    if (sizeof(Tcl_CallFrame) < sizeof(CallFrame)) {
	/*NOTREACHED*/
	Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame");
    }

#if defined(_WIN32) && !defined(_WIN64)
    if (sizeof(time_t) != 4) {
	/*NOTREACHED*/
	Tcl_Panic("<time.h> is not compatible with MSVC");




    }
    if ((TclOffset(Tcl_StatBuf,st_atime) != 32)
	    || (TclOffset(Tcl_StatBuf,st_ctime) != 40)) {
	/*NOTREACHED*/
	Tcl_Panic("<sys/stat.h> is not compatible with MSVC");
    }
#endif

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

    /*
     * Create an unsupported command for debugging bytecode.
     */

    Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
	    Tcl_DisassembleObjCmd, NULL, NULL);

    /* Create an unsupported command for timerate */
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::timerate",
	    Tcl_TimeRateObjCmd, NULL, NULL);

    /* Export unsupported commands */
    nsPtr = Tcl_FindNamespace(interp, "::tcl::unsupported", NULL, 0);
    if (nsPtr) {
	Tcl_Export(interp, nsPtr, "*", 1);
    }


#ifdef USE_DTRACE
    /*
     * Register the tcl::dtrace command.
     */

    Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
#endif /* USE_DTRACE */

    /*
     * Register the builtin math functions.
     */

    nsPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL);
    if (nsPtr == NULL) {
	Tcl_Panic("Can't create math function namespace");
    }
    strcpy(mathFuncName, "::tcl::mathfunc::");
#define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
    for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
	    builtinFuncPtr++) {
	strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
	Tcl_CreateObjCommand(interp, mathFuncName,
		builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL);
	Tcl_Export(interp, nsPtr, builtinFuncPtr->name, 0);
    }

    /*
     * Register the mathematical "operator" commands. [TIP #174]
     */

    nsPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
#define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
    if (nsPtr == NULL) {
	Tcl_Panic("can't create math operator namespace");
    }
    (void) Tcl_Export(interp, nsPtr, "*", 1);
    strcpy(mathFuncName, "::tcl::mathop::");
    for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
	TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)
		ckalloc(sizeof(TclOpCmdClientData));

	occdPtr->op = opcmdInfoPtr->name;
	occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs;







<
<
<
<
<
<
<
<
<
<
<













|
|









|






|

|


|







716
717
718
719
720
721
722











723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

    /*
     * Create an unsupported command for debugging bytecode.
     */

    Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
	    Tcl_DisassembleObjCmd, NULL, NULL);












#ifdef USE_DTRACE
    /*
     * Register the tcl::dtrace command.
     */

    Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
#endif /* USE_DTRACE */

    /*
     * Register the builtin math functions.
     */

    mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL);
    if (mathfuncNSPtr == NULL) {
	Tcl_Panic("Can't create math function namespace");
    }
    strcpy(mathFuncName, "::tcl::mathfunc::");
#define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
    for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
	    builtinFuncPtr++) {
	strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
	Tcl_CreateObjCommand(interp, mathFuncName,
		builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL);
	Tcl_Export(interp, mathfuncNSPtr, builtinFuncPtr->name, 0);
    }

    /*
     * Register the mathematical "operator" commands. [TIP #174]
     */

    mathopNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
#define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
    if (mathopNSPtr == NULL) {
	Tcl_Panic("can't create math operator namespace");
    }
    (void) Tcl_Export(interp, mathopNSPtr, "*", 1);
    strcpy(mathFuncName, "::tcl::mathop::");
    for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
	TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)
		ckalloc(sizeof(TclOpCmdClientData));

	occdPtr->op = opcmdInfoPtr->name;
	occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs;
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * Be careful to preserve
	 * any existing import links so we can restore them down below. That
	 * way, you can redefine a command and its import status will remain
	 * intact.
	 */








|







1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);
	
	/*
	 * Be careful to preserve
	 * any existing import links so we can restore them down below. That
	 * way, you can redefine a command and its import status will remain
	 * intact.
	 */

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * [***] This is wrong.  See Tcl Bug a16752c252.
	 * However, this buggy behavior is kept under particular
	 * circumstances to accommodate deployed binaries of the
	 * "tclcompiler" program. http://sourceforge.net/projects/tclpro/
	 * that crash if the bug is fixed.
	 */

	if (cmdPtr->objProc == TclInvokeStringCommand







|







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
	    break;
        }

	/* An existing command conflicts. Try to delete it.. */
	cmdPtr = Tcl_GetHashValue(hPtr);

	/*
	 * [***] This is wrong.  See Tcl Bug a16752c252.  
	 * However, this buggy behavior is kept under particular
	 * circumstances to accommodate deployed binaries of the
	 * "tclcompiler" program. http://sourceforge.net/projects/tclpro/
	 * that crash if the bug is fixed.
	 */

	if (cmdPtr->objProc == TclInvokeStringCommand
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200

	int nelements;
	Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
	CmdFrame *eoFramePtr = (CmdFrame *)
		TclStackAlloc(interp, sizeof(CmdFrame));

	eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
	eoFramePtr->level = (iPtr->cmdFramePtr == NULL?  1
		: iPtr->cmdFramePtr->level + 1);
	eoFramePtr->framePtr = iPtr->framePtr;
	eoFramePtr->nextPtr = iPtr->cmdFramePtr;

	eoFramePtr->nline = 0;
	eoFramePtr->line = NULL;








|







5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184

	int nelements;
	Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
	CmdFrame *eoFramePtr = (CmdFrame *)
		TclStackAlloc(interp, sizeof(CmdFrame));

	eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
	eoFramePtr->level = (iPtr->cmdFramePtr == NULL?  1 
		: iPtr->cmdFramePtr->level + 1);
	eoFramePtr->framePtr = iPtr->framePtr;
	eoFramePtr->nextPtr = iPtr->cmdFramePtr;

	eoFramePtr->nline = 0;
	eoFramePtr->line = NULL;

5582
5583
5584
5585
5586
5587
5588

5589
5590
5591
5592
5593
5594
5595
5596
5597

	d = *((const double *) internalPtr);
	Tcl_DecrRefCount(resultPtr);
	if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	resultPtr = Tcl_NewBignumObj(&big);

    }
    /* FALLTHRU */
    case TCL_NUMBER_LONG:
    case TCL_NUMBER_WIDE:
    case TCL_NUMBER_BIG:
	result = TclGetLongFromObj(interp, resultPtr, ptr);
	break;

    case TCL_NUMBER_NAN:







>

<







5566
5567
5568
5569
5570
5571
5572
5573
5574

5575
5576
5577
5578
5579
5580
5581

	d = *((const double *) internalPtr);
	Tcl_DecrRefCount(resultPtr);
	if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	resultPtr = Tcl_NewBignumObj(&big);
	/* FALLTHROUGH */
    }

    case TCL_NUMBER_LONG:
    case TCL_NUMBER_WIDE:
    case TCL_NUMBER_BIG:
	result = TclGetLongFromObj(interp, resultPtr, ptr);
	break;

    case TCL_NUMBER_NAN:
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
	    }
	}
	break;
    case TCL_NUMBER_BIG:
	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_isneg(&big)) {
	    mp_clear(&big);
	    goto negarg;
	}
	break;
    default:
	if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
	    return TCL_ERROR;







|







6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
	    }
	}
	break;
    case TCL_NUMBER_BIG:
	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (SIGN(&big) == MP_NEG) {
	    mp_clear(&big);
	    goto negarg;
	}
	break;
    default:
	if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
	    return TCL_ERROR;
6615
6616
6617
6618
6619
6620
6621

6622
6623
6624
6625
6626
6627
6628
6629
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
	return TCL_OK;
    }
#endif

    if (type == TCL_NUMBER_BIG) {

	if (mp_cmp_d(ptr, 0) == MP_LT) {
	    Tcl_GetBignumFromObj(NULL, objv[1], &big);
	tooLarge:
	    mp_neg(&big, &big);
	    Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
	} else {
	unChanged:
	    Tcl_SetObjResult(interp, objv[1]);







>
|







6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
	return TCL_OK;
    }
#endif

    if (type == TCL_NUMBER_BIG) {
	/* TODO: const correctness ? */
	if (mp_cmp_d((mp_int *) ptr, 0) == MP_LT) {
	    Tcl_GetBignumFromObj(NULL, objv[1], &big);
	tooLarge:
	    mp_neg(&big, &big);
	    Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
	} else {
	unChanged:
	    Tcl_SetObjResult(interp, objv[1]);
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
	/*
	 * Truncate the bignum; keep only bits in long range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &iResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
    return TCL_OK;







|







6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
	/*
	 * Truncate the bignum; keep only bits in long range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &iResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
    return TCL_OK;
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
	/*
	 * Truncate the bignum; keep only bits in wide int range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, CHAR_BIT * sizeof(Tcl_WideInt), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
    return TCL_OK;







|







6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
	/*
	 * Truncate the bignum; keep only bits in wide int range.
	 */

	mp_int big;

	Tcl_GetBignumFromObj(NULL, objPtr, &big);
	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
    return TCL_OK;
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
	mp_int big;

	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    /* TODO: more ::errorInfo here? or in caller? */
	    return TCL_ERROR;
	}

	mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &i);
	Tcl_DecrRefCount(objPtr);
    }

    /*







|







6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
	mp_int big;

	if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
	    /* TODO: more ::errorInfo here? or in caller? */
	    return TCL_ERROR;
	}

	mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
	objPtr = Tcl_NewBignumObj(&big);
	Tcl_IncrRefCount(objPtr);
	TclGetLongFromObj(NULL, objPtr, &i);
	Tcl_DecrRefCount(objPtr);
    }

    /*

Changes to generic/tclCkalloc.c.

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	    total_mallocs,
	    total_frees,
	    current_malloc_packets,
	    (unsigned long)current_bytes_malloced,
	    maximum_malloc_packets,
	    (unsigned long)maximum_bytes_malloced);
    if (flags == 0) {
	fprintf((FILE *)clientData, "%s", buf);
    } else {
	/* Assume objPtr to append to */
	Tcl_AppendToObj((Tcl_Obj *) clientData, buf, -1);
    }
    return 1;
}








|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	    total_mallocs,
	    total_frees,
	    current_malloc_packets,
	    (unsigned long)current_bytes_malloced,
	    maximum_malloc_packets,
	    (unsigned long)maximum_bytes_malloced);
    if (flags == 0) {
	fprintf((FILE *)clientData, buf);
    } else {
	/* Assume objPtr to append to */
	Tcl_AppendToObj((Tcl_Obj *) clientData, buf, -1);
    }
    return 1;
}


Changes to generic/tclClock.c.

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
    Tcl_Interp* interp,		/* Tcl interpreter */
    TclDateFields* fields,	/* Time to convert, with 'seconds' filled in */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    time_t tock;
    struct tm* timeVal;		/* Time after conversion */
    int diff;			/* Time zone diff local-Greenwich */
    char buffer[16];		/* Buffer for time zone name */

    /*
     * Use 'localtime' to determine local year, month, day, time of day.
     */

    tock = (time_t) fields->seconds;
    if ((Tcl_WideInt) tock != fields->seconds) {







|







1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
    Tcl_Interp* interp,		/* Tcl interpreter */
    TclDateFields* fields,	/* Time to convert, with 'seconds' filled in */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    time_t tock;
    struct tm* timeVal;		/* Time after conversion */
    int diff;			/* Time zone diff local-Greenwich */
    char buffer[8];		/* Buffer for time zone name */

    /*
     * Use 'localtime' to determine local year, month, day, time of day.
     */

    tock = (time_t) fields->seconds;
    if ((Tcl_WideInt) tock != fields->seconds) {
1735
1736
1737
1738
1739
1740
1741

1742

1743
1744
1745
1746
1747
1748
1749
#else
	Tcl_WideInt clicks = TclpGetWideClicks();
#endif
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) clicks));
	break;
    }
    case CLICKS_MICROS:

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));

	break;
    }

    return TCL_OK;
}

/*----------------------------------------------------------------------







>
|
>







1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
#else
	Tcl_WideInt clicks = TclpGetWideClicks();
#endif
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) clicks));
	break;
    }
    case CLICKS_MICROS:
	Tcl_GetTime(&now);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		((Tcl_WideInt) now.sec * 1000000) + now.usec));
	break;
    }

    return TCL_OK;
}

/*----------------------------------------------------------------------
1804
1805
1806
1807
1808
1809
1810


1811
1812
1813
1814

1815

1816
1817
1818
1819
1820
1821
1822
int
ClockMicrosecondsObjCmd(
    ClientData clientData,	/* Client data is unused */
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj* const* objv)	/* Parameter values */
{


    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));

    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ClockParseformatargsObjCmd --







>
>




>
|
>







1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
int
ClockMicrosecondsObjCmd(
    ClientData clientData,	/* Client data is unused */
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj* const* objv)	/* Parameter values */
{
    Tcl_Time now;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
	    ((Tcl_WideInt) now.sec * 1000000) + now.usec));
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ClockParseformatargsObjCmd --

Changes to generic/tclCmdAH.c.

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	/*
	 * Check for special case of single pattern (no list) with no
	 * backslash sequences.
	 */

	pat = TclGetString(caseObjv[i]);
	for (p = pat; *p != '\0'; p++) {
	    if (TclIsSpaceProcM(*p) || (*p == '\\')) {
		break;
	    }
	}
	if (*p == '\0') {
	    if ((*pat == 'd') && (strcmp(pat, "default") == 0)) {
		body = i + 1;
	    }







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	/*
	 * Check for special case of single pattern (no list) with no
	 * backslash sequences.
	 */

	pat = TclGetString(caseObjv[i]);
	for (p = pat; *p != '\0'; p++) {
	    if (TclIsSpaceProc(*p) || (*p == '\\')) {
		break;
	    }
	}
	if (*p == '\0') {
	    if ((*pat == 'd') && (strcmp(pat, "default") == 0)) {
		body = i + 1;
	    }
866
867
868
869
870
871
872
873




874

875
876
877
878
879
880
881
882
883
884
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    Tcl_WideInt newTime;






	    
	    if (Tcl_GetWideIntFromObj(interp, objv[3], &newTime) != TCL_OK) {
		    return TCL_ERROR;
	    }

	    if (index == FCMD_ATIME) {
		tval.actime = newTime;
		tval.modtime = buf.st_mtime;
	    } else {	/* index == FCMD_MTIME */
		tval.actime = buf.st_atime;







<
>
>
>
>

>
|
|
|







866
867
868
869
870
871
872

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc == 4) {

	    /*
	     * Need separate variable for reading longs from an object on
	     * 64-bit platforms. [Bug #698146]
	     */

	    long newTime;

	    if (TclGetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
		return TCL_ERROR;
	    }

	    if (index == FCMD_ATIME) {
		tval.actime = newTime;
		tval.modtime = buf.st_mtime;
	    } else {	/* index == FCMD_MTIME */
		tval.actime = buf.st_atime;
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
	     */

	    if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
		return TCL_ERROR;
	    }
	}

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(index == FCMD_ATIME ? buf.st_atime : buf.st_mtime)));
	return TCL_OK;
    case FCMD_ATTRIBUTES:
	return TclFileAttrsCmd(interp, objc, objv);
    case FCMD_CHANNELS:
	if ((objc < 2) || (objc > 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");







|







904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
	     */

	    if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
		return TCL_ERROR;
	    }
	}

	Tcl_SetObjResult(interp, Tcl_NewLongObj((long)
		(index == FCMD_ATIME ? buf.st_atime : buf.st_mtime)));
	return TCL_OK;
    case FCMD_ATTRIBUTES:
	return TclFileAttrsCmd(interp, objc, objv);
    case FCMD_CHANNELS:
	if ((objc < 2) || (objc > 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
    STORE_ARY("size",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    STORE_ARY("blocks",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    STORE_ARY("blksize", Tcl_NewLongObj((long)statPtr->st_blksize));
#endif
    STORE_ARY("atime",	Tcl_NewWideIntObj(statPtr->st_atime));
    STORE_ARY("mtime",	Tcl_NewWideIntObj(statPtr->st_mtime));
    STORE_ARY("ctime",	Tcl_NewWideIntObj(statPtr->st_ctime));
    mode = (unsigned short) statPtr->st_mode;
    STORE_ARY("mode",	Tcl_NewIntObj(mode));
    STORE_ARY("type",	Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ARY

    return TCL_OK;
}







|
|
|







1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
    STORE_ARY("size",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    STORE_ARY("blocks",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    STORE_ARY("blksize", Tcl_NewLongObj((long)statPtr->st_blksize));
#endif
    STORE_ARY("atime",	Tcl_NewLongObj((long)statPtr->st_atime));
    STORE_ARY("mtime",	Tcl_NewLongObj((long)statPtr->st_mtime));
    STORE_ARY("ctime",	Tcl_NewLongObj((long)statPtr->st_ctime));
    mode = (unsigned short) statPtr->st_mode;
    STORE_ARY("mode",	Tcl_NewIntObj(mode));
    STORE_ARY("type",	Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ARY

    return TCL_OK;
}

Changes to generic/tclCmdIL.c.

3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int i, j, index, indices, length, nocase = 0, indexc;
    int sortMode = SORTMODE_ASCII;
    Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
    size_t elmArrSize;
    SortElement *elementArray, *elementPtr;
    SortInfo sortInfo;		/* Information about this sort that needs to
				 * be passed to the comparison function. */
    static const char *switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
	"-index", "-indices", "-integer", "-nocase", "-real", "-unique", NULL
    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
	LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
    };

    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort. Element i of the array holds a list of length 2**i.
     */
#   define MAXCALLOC 1024000
#   define NUM_LISTS 30
    SortElement *subList[NUM_LISTS+1];

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
	return TCL_ERROR;
    }







<

















<







3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496

3497
3498
3499
3500
3501
3502
3503
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int i, j, index, indices, length, nocase = 0, indexc;
    int sortMode = SORTMODE_ASCII;
    Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;

    SortElement *elementArray, *elementPtr;
    SortInfo sortInfo;		/* Information about this sort that needs to
				 * be passed to the comparison function. */
    static const char *switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
	"-index", "-indices", "-integer", "-nocase", "-real", "-unique", NULL
    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
	LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
    };

    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort. Element i of the array holds a list of length 2**i.
     */

#   define NUM_LISTS 30
    SortElement *subList[NUM_LISTS+1];

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
	return TCL_ERROR;
    }
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
    }

    /*
     * The following loop creates a SortElement for each list element and
     * begins sorting it into the sublists as it appears.
     */

    elmArrSize = length * sizeof(SortElement);
    if (elmArrSize <= MAXCALLOC) {
	elementArray = (SortElement *) ckalloc(elmArrSize);
    } else {
	elementArray = (SortElement *) malloc(elmArrSize);
    }
    if (!elementArray) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no enough memory to proccess sort of %d items", length));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	sortInfo.resultCode = TCL_ERROR;
	goto done;
    }

    for (i=0; i < length; i++){
	if (indexc) {
	    /*
	     * If this is an indexed sort, retrieve the corresponding element
	     */
	    indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);







<
<
|
<
<
<
<
<
<
<
<
<
<







3695
3696
3697
3698
3699
3700
3701


3702










3703
3704
3705
3706
3707
3708
3709
    }

    /*
     * The following loop creates a SortElement for each list element and
     * begins sorting it into the sublists as it appears.
     */



    elementArray = (SortElement *) ckalloc( length * sizeof(SortElement));











    for (i=0; i < length; i++){
	if (indexc) {
	    /*
	     * If this is an indexed sort, retrieve the corresponding element
	     */
	    indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
	    }
	}
	listRepPtr->elemCount = i;
	Tcl_SetObjResult(interp, resultPtr);
    }

  done1:
    if (elmArrSize <= MAXCALLOC) {
	ckfree((char *)elementArray);
    } else {
	free((char *)elementArray);
    }

  done:
    if (sortMode == SORTMODE_COMMAND) {
	TclDecrRefCount(sortInfo.compareCmdPtr);
	TclDecrRefCount(listObj);
	sortInfo.compareCmdPtr = NULL;
    }







<
|
<
<
<







3798
3799
3800
3801
3802
3803
3804

3805



3806
3807
3808
3809
3810
3811
3812
	    }
	}
	listRepPtr->elemCount = i;
	Tcl_SetObjResult(interp, resultPtr);
    }

  done1:

    ckfree((char *)elementArray);




  done:
    if (sortMode == SORTMODE_COMMAND) {
	TclDecrRefCount(sortInfo.compareCmdPtr);
	TclDecrRefCount(listObj);
	sortInfo.compareCmdPtr = NULL;
    }

Changes to generic/tclCmdMZ.c.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * Copyright (c) 2003 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
#include "tclRegexp.h"

static int		UniCharIsAscii(int character);
static int		UniCharIsHexDigit(int character);

/*
 *----------------------------------------------------------------------







<







13
14
15
16
17
18
19

20
21
22
23
24
25
26
 * Copyright (c) 2003 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

#include "tclRegexp.h"

static int		UniCharIsAscii(int character);
static int		UniCharIsHexDigit(int character);

/*
 *----------------------------------------------------------------------
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
		     * the number of bytes when parsing strings with non-ASCII
		     * characters in them.
		     *
		     * Skip leading spaces first. This is only really an issue
		     * if it is the first "element" that has the failure.
		     */

		    while (TclIsSpaceProcM(*p)) {
			p++;
		    }
		    TclNewStringObj(tmpStr, string1, p-string1);
		    failat = Tcl_GetCharLength(tmpStr);
		    TclDecrRefCount(tmpStr);
		    break;
		}







|







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
		     * the number of bytes when parsing strings with non-ASCII
		     * characters in them.
		     *
		     * Skip leading spaces first. This is only really an issue
		     * if it is the first "element" that has the failure.
		     */

		    while (TclIsSpaceProc(*p)) {
			p++;
		    }
		    TclNewStringObj(tmpStr, string1, p-string1);
		    failat = Tcl_GetCharLength(tmpStr);
		    TclDecrRefCount(tmpStr);
		    break;
		}
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
    string = TclGetStringFromObj(objv[1], &length);
    if (index >= numChars) {
	index = numChars - 1;
    }
    cur = 0;
    if (index > 0) {
	p = Tcl_UtfAtIndex(string, index);

	TclUtfToUniChar(p, &ch);
	for (cur = index; cur >= 0; cur--) {
	    int delta = 0;
	    const char *next;

	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }

	    next = TclUtfPrev(p, string);
	    do {
		next += delta;
		delta = TclUtfToUniChar(next, &ch);
	    } while (next + delta < p);
	    p = next;
	}
	if (cur != index) {
	    cur += 1;
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(cur));
    return TCL_OK;







|
|
<
<
<
<



<
|
<
<
<
<
<







2391
2392
2393
2394
2395
2396
2397
2398
2399




2400
2401
2402

2403





2404
2405
2406
2407
2408
2409
2410
    string = TclGetStringFromObj(objv[1], &length);
    if (index >= numChars) {
	index = numChars - 1;
    }
    cur = 0;
    if (index > 0) {
	p = Tcl_UtfAtIndex(string, index);
	for (cur = index; cur >= 0; cur--) {
	    TclUtfToUniChar(p, &ch);




	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }

	    p = Tcl_UtfPrev(p, string);





	}
	if (cur != index) {
	    cur += 1;
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(cur));
    return TCL_OK;
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
#endif

    if (count <= 1) {
	/*
	 * Use int obj since we know time is not fractional. [Bug 1202178]
	 */

	objs[0] = Tcl_NewWideIntObj((count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec);
    } else {
	objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
    }

    /*
     * Construct the result as a list because many programs have always parsed
     * as such (extracting the first element, typically).
     */

    TclNewLiteralStringObj(objs[1], "microseconds");
    TclNewLiteralStringObj(objs[2], "per");
    TclNewLiteralStringObj(objs[3], "iteration");
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_TimeRateObjCmd --
 *
 *	This object-based procedure is invoked to process the "timerate" Tcl
 *	command.
 *
 *	This is similar to command "time", except the execution limited by
 *	given time (in milliseconds) instead of repetition count.
 *
 * Example:
 *	timerate {after 5} 1000; # equivalent to: time {after 5} [expr 1000/5]
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeRateObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static double measureOverhead = 0;
				/* global measure-overhead */
    double overhead = -1;	/* given measure-overhead */
    register Tcl_Obj *objPtr;
    register int result, i;
    Tcl_Obj *calibrate = NULL, *direct = NULL;
    TclWideMUInt count = 0;	/* Holds repetition count */
    Tcl_WideInt maxms = WIDE_MIN;
				/* Maximal running time (in milliseconds) */
    TclWideMUInt maxcnt = WIDE_MAX;
				/* Maximal count of iterations. */
    TclWideMUInt threshold = 1;	/* Current threshold for check time (faster
				 * repeat count without time check) */
    TclWideMUInt maxIterTm = 1;	/* Max time of some iteration as max
				 * threshold, additionally avoiding divide to
				 * zero (i.e., never < 1) */
    unsigned short factor = 50;	/* Factor (4..50) limiting threshold to avoid
				 * growth of execution time. */
    register Tcl_WideInt start, middle, stop;
#ifndef TCL_WIDE_CLICKS
    Tcl_Time now;
#endif /* !TCL_WIDE_CLICKS */
    static const char *const options[] = {
	"-direct",	"-overhead",	"-calibrate",	"--",	NULL
    };
    enum options {
	TMRT_EV_DIRECT,	TMRT_OVERHEAD,	TMRT_CALIBRATE,	TMRT_LAST
    };
    ByteCode *codePtr = NULL;

    for (i = 1; i < objc - 1; i++) {
	int index;

	if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    break;
	}
	if (index == TMRT_LAST) {
	    i++;
	    break;
	}
	switch (index) {
	case TMRT_EV_DIRECT:
	    direct = objv[i];
	    break;
	case TMRT_OVERHEAD:
	    if (++i >= objc - 1) {
		goto usage;
	    }
	    if (Tcl_GetDoubleFromObj(interp, objv[i], &overhead) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	case TMRT_CALIBRATE:
	    calibrate = objv[i];
	    break;
	}
    }

    if (i >= objc || i < objc - 3) {
    usage:
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-direct? ?-calibrate? ?-overhead double? "
		"command ?time ?max-count??");
	return TCL_ERROR;
    }
    objPtr = objv[i++];
    if (i < objc) {	/* max-time */
	result = Tcl_GetWideIntFromObj(interp, objv[i++], &maxms);
	if (result != TCL_OK) {
	    return result;
	}
	if (i < objc) {	/* max-count*/
	    Tcl_WideInt v;

	    result = Tcl_GetWideIntFromObj(interp, objv[i], &v);
	    if (result != TCL_OK) {
		return result;
	    }
	    maxcnt = (v > 0) ? v : 0;
	}
    }

    /*
     * If we are doing calibration.
     */

    if (calibrate) {
	/*
	 * If no time specified for the calibration.
	 */

	if (maxms == WIDE_MIN) {
	    Tcl_Obj *clobjv[6];
	    Tcl_WideInt maxCalTime = 5000;
	    double lastMeasureOverhead = measureOverhead;

	    clobjv[0] = objv[0];
	    i = 1;
	    if (direct) {
		clobjv[i++] = direct;
	    }
	    clobjv[i++] = objPtr;

	    /*
	     * Reset last measurement overhead.
	     */

	    measureOverhead = (double) 0;

	    /*
	     * Self-call with 100 milliseconds to warm-up, before entering the
	     * calibration cycle.
	     */

	    TclNewLongObj(clobjv[i], 100);
	    Tcl_IncrRefCount(clobjv[i]);
	    result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv);
	    Tcl_DecrRefCount(clobjv[i]);
	    if (result != TCL_OK) {
		return result;
	    }

	    i--;
	    clobjv[i++] = calibrate;
	    clobjv[i++] = objPtr;

	    /*
	     * Set last measurement overhead to max.
	     */

	    measureOverhead = (double) UWIDE_MAX;

	    /*
	     * Run the calibration cycle until it is more precise.
	     */

	    maxms = -1000;
	    do {
		lastMeasureOverhead = measureOverhead;
		TclNewLongObj(clobjv[i], (int) maxms);
		Tcl_IncrRefCount(clobjv[i]);
		result = Tcl_TimeRateObjCmd(NULL, interp, i + 1, clobjv);
		Tcl_DecrRefCount(clobjv[i]);
		if (result != TCL_OK) {
		    return result;
		}
		maxCalTime += maxms;

		/*
		 * Increase maxms for more precise calibration.
		 */

		maxms -= -maxms / 4;

		/*
		 * As long as new value more as 0.05% better
		 */
	    } while ((measureOverhead >= lastMeasureOverhead
		    || measureOverhead / lastMeasureOverhead <= 0.9995)
		    && maxCalTime > 0);

	    return result;
	}
	if (maxms == 0) {
	    /*
	     * Reset last measurement overhead
	     */

	    measureOverhead = 0;
	    Tcl_SetObjResult(interp, Tcl_NewLongObj(0));
	    return TCL_OK;
	}

	/*
	 * If time is negative, make current overhead more precise.
	 */

	if (maxms > 0) {
	    /*
	     * Set last measurement overhead to max.
	     */

	    measureOverhead = (double) UWIDE_MAX;
	} else {
	    maxms = -maxms;
	}
    }

    if (maxms == WIDE_MIN) {
	maxms = 1000;
    }
    if (overhead == -1) {
	overhead = measureOverhead;
    }

    /*
     * Ensure that resetting of result will not smudge the further
     * measurement.
     */

    Tcl_ResetResult(interp);

    /*
     * Compile object if needed.
     */

    if (!direct) {
	if (TclInterpReady(interp) != TCL_OK) {
	    return TCL_ERROR;
	}
	codePtr = TclCompileObj(interp, objPtr, NULL, 0);
	TclPreserveByteCode(codePtr);
    }

    /*
     * Get start and stop time.
     */

#ifdef TCL_WIDE_CLICKS
    start = middle = TclpGetWideClicks();

    /*
     * Time to stop execution (in wide clicks).
     */

    stop = start + (maxms * 1000 / TclpWideClickInMicrosec());
#else
    Tcl_GetTime(&now);
    start = now.sec;
    start *= 1000000;
    start += now.usec;
    middle = start;

    /*
     * Time to stop execution (in microsecs).
     */

    stop = start + maxms * 1000;
#endif /* TCL_WIDE_CLICKS */

    /*
     * Start measurement.
     */

    if (maxcnt > 0) {
	while (1) {
	    /*
	     * Evaluate a single iteration.
	     */

	    count++;
	    if (!direct) {		/* precompiled */
		/*
		 * Use loop optimized TEBC call (TCL_EVAL_DISCARD_RESULT): it's a part of
		 * iteration, this way evaluation will be more similar to a cycle (also
		 * avoids extra overhead to set result to interp, etc.)
		 */
		((Interp *)interp)->evalFlags |= TCL_EVAL_DISCARD_RESULT;
		result = TclExecuteByteCode(interp, codePtr);
	    } else {			/* eval */
		result = TclEvalObjEx(interp, objPtr, 0, NULL, 0);
	    }
	    /*
	     * Allow break and continue from measurement cycle (used for
	     * conditional stop and flow control of iterations).
	     */

	    switch (result) {
		case TCL_OK:
		    break;
		case TCL_BREAK:
		    /*
		     * Force stop immediately.
		     */
		    threshold = 1;
		    maxcnt = 0;
		    /* FALLTHRU */
		case TCL_CONTINUE:
		    result = TCL_OK;
		    break;
		default:
		    goto done;
	    }

	    /*
	     * Don't check time up to threshold.
	     */

	    if (--threshold > 0) {
		continue;
	    }

	    /*
	     * Check stop time reached, estimate new threshold.
	     */

#ifdef TCL_WIDE_CLICKS
	    middle = TclpGetWideClicks();
#else
	    Tcl_GetTime(&now);
	    middle = now.sec;
	    middle *= 1000000;
	    middle += now.usec;
#endif /* TCL_WIDE_CLICKS */

	    if (middle >= stop || count >= maxcnt) {
		break;
	    }

	    /*
	     * Don't calculate threshold by few iterations, because sometimes
	     * first iteration(s) can be too fast or slow (cached, delayed
	     * clean up, etc).
	     */

	    if (count < 10) {
		threshold = 1;
		continue;
	    }

	    /*
	     * Average iteration time in microsecs.
	     */

	    threshold = (middle - start) / count;
	    if (threshold > maxIterTm) {
		maxIterTm = threshold;
		/*
		 * Iterations seem to be longer.
		 */
		if (threshold > maxIterTm * 2) {
		    factor *= 2;
		    if (factor > 50) {
			factor = 50;
		    }
		} else {
		    if (factor < 50) {
			factor++;
		    }
		}
	    } else if (factor > 4) {
		/*
		 * Iterations seem to be shorter.
		 */

		if (threshold < (maxIterTm / 2)) {
		    factor /= 2;
		    if (factor < 4) {
			factor = 4;
		    }
		} else {
		    factor--;
		}
	    }

	    /*
	     * As relation between remaining time and time since last check,
	     * maximal some % of time (by factor), so avoid growing of the
	     * execution time if iterations are not consistent, e.g. was
	     * continuously on time).
	     */

	    threshold = ((stop - middle) / maxIterTm) / factor + 1;
	    if (threshold > 100000) {	/* fix for too large threshold */
		threshold = 100000;
	    }

	    /*
	     * Consider max-count
	     */

	    if (threshold > maxcnt - count) {
		threshold = maxcnt - count;
	    }
	}
    }

    {
	Tcl_Obj *objarr[8], **objs = objarr;
	TclWideMUInt usec, val;
	int digits;

	/*
	 * Absolute execution time in microseconds or in wide clicks.
	 */
	usec = (TclWideMUInt)(middle - start);

#ifdef TCL_WIDE_CLICKS
	/*
	 * convert execution time (in wide clicks) to microsecs.
	 */

	usec *= TclpWideClickInMicrosec();
#endif /* TCL_WIDE_CLICKS */

	if (!count) {		/* no iterations - avoid divide by zero */
	    objs[0] = objs[2] = objs[4] = Tcl_NewWideIntObj(0);
	    goto retRes;
	}

	/*
	 * If not calibrating...
	 */

	if (!calibrate) {
	    /*
	     * Minimize influence of measurement overhead.
	     */

	    if (overhead > 0) {
		/*
		 * Estimate the time of overhead (microsecs).
		 */

		TclWideMUInt curOverhead = overhead * count;

		if (usec > curOverhead) {
		    usec -= curOverhead;
		} else {
		    usec = 0;
		}
	    }
	} else {
	    /*
	     * Calibration: obtaining new measurement overhead.
	     */

	    if (measureOverhead > ((double) usec) / count) {
		measureOverhead = ((double) usec) / count;
	    }
	    objs[0] = Tcl_NewDoubleObj(measureOverhead);
	    TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */
	    objs += 2;
	}

	val = usec / count;		/* microsecs per iteration */
	if (val >= 1000000) {
	    objs[0] = Tcl_NewWideIntObj(val);
	} else {
	    if (val < 10) {
		digits = 6;
	    } else if (val < 100) {
		digits = 4;
	    } else if (val < 1000) {
		digits = 3;
	    } else if (val < 10000) {
		digits = 2;
	    } else {
		digits = 1;
	    }
	    objs[0] = Tcl_ObjPrintf("%.*f", digits, ((double) usec)/count);
	}

	objs[2] = Tcl_NewWideIntObj(count); /* iterations */

	/*
	 * Calculate speed as rate (count) per sec
	 */

	if (!usec) {
	    usec++;			/* Avoid divide by zero. */
	}
	if (count < (WIDE_MAX / 1000000)) {
	    val = (count * 1000000) / usec;
	    if (val < 100000) {
		if (val < 100) {
		    digits = 3;
		} else if (val < 1000) {
		    digits = 2;
		} else {
		    digits = 1;
		}
		objs[4] = Tcl_ObjPrintf("%.*f",
			digits, ((double) (count * 1000000)) / usec);
	    } else {
		objs[4] = Tcl_NewWideIntObj(val);
	    }
	} else {
	    objs[4] = Tcl_NewWideIntObj((count / usec) * 1000000);
	}

    retRes:
	/*
	 * Estimated net execution time (in millisecs).
	 */

	if (!calibrate) {
	    if (usec >= 1) {
		objs[6] = Tcl_ObjPrintf("%.3f", (double)usec / 1000);
	    } else {
		objs[6] = Tcl_NewWideIntObj(0);
	    }
	    TclNewLiteralStringObj(objs[7], "net-ms");
	}

	/*
	 * Construct the result as a list because many programs have always
	 * parsed as such (extracting the first element, typically).
	 */

	TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#"); /* mics/# */
	TclNewLiteralStringObj(objs[3], "#");
	TclNewLiteralStringObj(objs[5], "#/sec");
	Tcl_SetObjResult(interp, Tcl_NewListObj(8, objarr));
    }

  done:
    if (codePtr != NULL) {
	TclReleaseByteCode(codePtr);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WhileObjCmd --
 *
 *	This procedure is invoked to process the "while" Tcl command. See the







|
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
































































































































































































































































































































































































































































































































































3951
3952
3953
3954
3955
3956
3957
#endif

    if (count <= 1) {
	/*
	 * Use int obj since we know time is not fractional. [Bug 1202178]
	 */

	objs[0] = Tcl_NewIntObj((count <= 0) ? 0 : (int) totalMicroSec);
    } else {
	objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
    }

    /*
     * Construct the result as a list because many programs have always parsed
     * as such (extracting the first element, typically).
     */

    TclNewLiteralStringObj(objs[1], "microseconds");
    TclNewLiteralStringObj(objs[2], "per");
    TclNewLiteralStringObj(objs[3], "iteration");
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));

    return TCL_OK;
}

































































































































































































































































































































































































































































































































































/*
 *----------------------------------------------------------------------
 *
 * Tcl_WhileObjCmd --
 *
 *	This procedure is invoked to process the "while" Tcl command. See the

Changes to generic/tclCompExpr.c.

570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
				 * aim is just a parse, or whether it will go
				 * on to compile the expression.  Different
				 * optimizations are appropriate for the
				 * two scenarios. */
{
    OpNode *nodes = NULL;	/* Pointer to the OpNode storage array where
				 * we build the parse tree. */
    unsigned nodesAvailable = 64;	/* Initial size of the storage array.  This
				 * value establishes a minimum tree memory cost
				 * of only about 1 kibyte, and is large enough
				 * for most expressions to parse with no need
				 * for array growth and reallocation. */
    unsigned nodesUsed = 0;		/* Number of OpNodes filled. */
    int scanned = 0;		/* Capture number of byte scanned by
				 * parsing routines. */
    int lastParsed;		/* Stores info about what the lexeme parsed
				 * the previous pass through the parsing loop
				 * was.  If it was an operator, lastParsed is
				 * the index of the OpNode for that operator.
				 * If it was not an operator, lastParsed holds







|




|







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
				 * aim is just a parse, or whether it will go
				 * on to compile the expression.  Different
				 * optimizations are appropriate for the
				 * two scenarios. */
{
    OpNode *nodes = NULL;	/* Pointer to the OpNode storage array where
				 * we build the parse tree. */
    int nodesAvailable = 64;	/* Initial size of the storage array.  This
				 * value establishes a minimum tree memory cost
				 * of only about 1 kibyte, and is large enough
				 * for most expressions to parse with no need
				 * for array growth and reallocation. */
    int nodesUsed = 0;		/* Number of OpNodes filled. */
    int scanned = 0;		/* Capture number of byte scanned by
				 * parsing routines. */
    int lastParsed;		/* Stores info about what the lexeme parsed
				 * the previous pass through the parsing loop
				 * was.  If it was an operator, lastParsed is
				 * the index of the OpNode for that operator.
				 * If it was not an operator, lastParsed holds
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

	/*
	 * Each pass through this loop adds up to one more OpNode. Allocate
	 * space for one if required.
	 */

	if (nodesUsed >= nodesAvailable) {
	    unsigned size = nodesUsed * 2;
	    OpNode *newPtr = NULL;

	    do {
	      if (size <= UINT_MAX/sizeof(OpNode)) {
		newPtr = (OpNode *) attemptckrealloc((char *) nodes,
			(unsigned int) size * sizeof(OpNode));
	      }







|







654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

	/*
	 * Each pass through this loop adds up to one more OpNode. Allocate
	 * space for one if required.
	 */

	if (nodesUsed >= nodesAvailable) {
	    int size = nodesUsed * 2;
	    OpNode *newPtr = NULL;

	    do {
	      if (size <= UINT_MAX/sizeof(OpNode)) {
		newPtr = (OpNode *) attemptckrealloc((char *) nodes,
			(unsigned int) size * sizeof(OpNode));
	      }

Changes to generic/tclCompile.c.

1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
    int bytesLeft, isFirstCmd, wordIdx, currCmdIndex;
    int commandLength, objIndex;
    Tcl_DString ds;
    /* TIP #280 */
    ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr;
    int *wlines, wlineat, cmdLine;
    int* clNext;
    Tcl_Parse *parsePtr;


    if (envPtr->iPtr == NULL) {
	Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv");
    }
    /* 
     * Check depth to avoid overflow of the C execution stack by too many
     * nested calls of TclCompileScript (considering interp recursionlimit).
     * Factor 5/4 (1.25) is used to avoid too mistaken limit recognition
     * during "mixed" evaluation and compilation process (nested eval+compile)
     * and is good enough for default recursionlimit (1000).
     */
    if (iPtr->numLevels / 5 > iPtr->maxNestingDepth / 4) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "too many nested compilations (infinite loop?)", -1));
	Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL);
	TclCompileSyntaxError(interp, envPtr);
	return;
    }
    /* 
     * Avoid stack exhaustion by too many nested calls of TclCompileScript
     * (considering interp recursionlimit).
     */
    iPtr->numLevels++;

    parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));

    Tcl_DStringInit(&ds);

    if (numBytes < 0) {
	numBytes = strlen(script);
    }
    Tcl_ResetResult(interp);







|
>




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226





















1227
1228
1229
1230
1231
1232
1233
    int bytesLeft, isFirstCmd, wordIdx, currCmdIndex;
    int commandLength, objIndex;
    Tcl_DString ds;
    /* TIP #280 */
    ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr;
    int *wlines, wlineat, cmdLine;
    int* clNext;
    Tcl_Parse *parsePtr = (Tcl_Parse *)
	    TclStackAlloc(interp, sizeof(Tcl_Parse));

    if (envPtr->iPtr == NULL) {
	Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv");
    }






















    Tcl_DStringInit(&ds);

    if (numBytes < 0) {
	numBytes = strlen(script);
    }
    Tcl_ResetResult(interp);
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
     * self-reference, but now opt for avoiding its creation altogether.
     */

    if (envPtr->codeNext == entryCodeNext) {
	TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewObj(), NULL), envPtr);
    }

    iPtr->numLevels--;
    TclStackFree(interp, parsePtr);
    Tcl_DStringFree(&ds);
}

/*
 *----------------------------------------------------------------------
 *







<







1627
1628
1629
1630
1631
1632
1633

1634
1635
1636
1637
1638
1639
1640
     * self-reference, but now opt for avoiding its creation altogether.
     */

    if (envPtr->codeNext == entryCodeNext) {
	TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewObj(), NULL), envPtr);
    }


    TclStackFree(interp, parsePtr);
    Tcl_DStringFree(&ds);
}

/*
 *----------------------------------------------------------------------
 *

Changes to generic/tclCompile.h.

855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
			    CONST char *command, int length, int flags);
/*
 *----------------------------------------------------------------
 * Procedures exported by the engine to be used by tclBasic.c
 *----------------------------------------------------------------
 */

MODULE_SCOPE ByteCode *	TclCompileObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const CmdFrame *invoker, int word);

MODULE_SCOPE int	TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const CmdFrame *invoker, int word);

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl bytecode compilation and execution modules but
 * not used outside:







<
<
<







855
856
857
858
859
860
861



862
863
864
865
866
867
868
			    CONST char *command, int length, int flags);
/*
 *----------------------------------------------------------------
 * Procedures exported by the engine to be used by tclBasic.c
 *----------------------------------------------------------------
 */




MODULE_SCOPE int	TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const CmdFrame *invoker, int word);

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl bytecode compilation and execution modules but
 * not used outside:
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
#endif
MODULE_SCOPE int	TclPrintInstruction(ByteCode* codePtr,
			    unsigned char *pc);
MODULE_SCOPE void	TclPrintObject(FILE *outFile,
			    Tcl_Obj *objPtr, int maxChars);
MODULE_SCOPE void	TclPrintSource(FILE *outFile,
			    CONST char *string, int maxChars);

static inline void
TclPreserveByteCode(
    register ByteCode *codePtr)
{
    codePtr->refCount++;
}

static inline void
TclReleaseByteCode(
    register ByteCode *codePtr)
{
    if (codePtr->refCount-- > 1) {
	return;
    }
    /* Just dropped to refcount==0.  Clean up. */
    TclCleanupByteCode(codePtr);
}

MODULE_SCOPE void	TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
MODULE_SCOPE int	TclSingleOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclSortingOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);







|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<







931
932
933
934
935
936
937
938






939











940
941
942
943
944
945
946
#endif
MODULE_SCOPE int	TclPrintInstruction(ByteCode* codePtr,
			    unsigned char *pc);
MODULE_SCOPE void	TclPrintObject(FILE *outFile,
			    Tcl_Obj *objPtr, int maxChars);
MODULE_SCOPE void	TclPrintSource(FILE *outFile,
			    CONST char *string, int maxChars);
MODULE_SCOPE int	TclRegisterLiteral(CompileEnv *envPtr,






			    char *bytes, int length, int flags);











MODULE_SCOPE void	TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
MODULE_SCOPE int	TclSingleOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclSortingOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
 * Define the following macros to enable debug logging of the DTrace proc,
 * cmd, and inst probes. Note that this does _not_ require a platform with
 * DTrace, it simply logs all probe output to /tmp/tclDTraceDebug-[pid].log.
 *
 * If the second macro is defined, logging to file starts immediately,
 * otherwise only after the first call to [tcl::dtrace]. Note that the debug
 * probe data is always computed, even when it is not logged to file.
 *
 * Defining the third macro enables debug logging of inst probes (disabled
 * by default due to the significant performance impact).
 */

/*
#define TCL_DTRACE_DEBUG 1
#define TCL_DTRACE_DEBUG_LOG_ENABLED 1







|







1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
 * Define the following macros to enable debug logging of the DTrace proc,
 * cmd, and inst probes. Note that this does _not_ require a platform with
 * DTrace, it simply logs all probe output to /tmp/tclDTraceDebug-[pid].log.
 *
 * If the second macro is defined, logging to file starts immediately,
 * otherwise only after the first call to [tcl::dtrace]. Note that the debug
 * probe data is always computed, even when it is not logged to file.
 * 
 * Defining the third macro enables debug logging of inst probes (disabled
 * by default due to the significant performance impact).
 */

/*
#define TCL_DTRACE_DEBUG 1
#define TCL_DTRACE_DEBUG_LOG_ENABLED 1

Changes to generic/tclDate.c.

1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
#endif
#endif
{
  /* The look-ahead symbol.  */
int yychar;

/* The semantic value of the look-ahead symbol.  */
YYSTYPE yylval = {0};

/* Number of syntax errors so far.  */
int yynerrs;
/* Location data for the look-ahead symbol.  */
YYLTYPE yylloc;

  int yystate;







|







1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
#endif
#endif
{
  /* The look-ahead symbol.  */
int yychar;

/* The semantic value of the look-ahead symbol.  */
YYSTYPE yylval;

/* Number of syntax errors so far.  */
int yynerrs;
/* Location data for the look-ahead symbol.  */
YYLTYPE yylloc;

  int yystate;
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
    register char c;
    register char *p;
    char buff[20];
    int Count;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProcM(*yyInput)) {
	    yyInput++;
	}

	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
	    /*
	     * Convert the string into a number; count the number of digits.
	     */







|







2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
    register char c;
    register char *p;
    char buff[20];
    int Count;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProc(*yyInput)) {
	    yyInput++;
	}

	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
	    /*
	     * Convert the string into a number; count the number of digits.
	     */
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
    }
}

int
TclClockOldscanObjCmd(
    ClientData clientData,	/* Unused */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of parameters */
    Tcl_Obj *CONST *objv)	/* Parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;







|







2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
    }
}

int
TclClockOldscanObjCmd(
    ClientData clientData,	/* Unused */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *CONST *objv)	/* Parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;

Changes to generic/tclDecls.h.

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/* 30 */
EXTERN void		TclFreeObj(Tcl_Obj *objPtr);
#endif
#ifndef Tcl_GetBoolean_TCL_DECLARED
#define Tcl_GetBoolean_TCL_DECLARED
/* 31 */
EXTERN int		Tcl_GetBoolean(Tcl_Interp *interp, CONST char *src,
				int *intPtr);
#endif
#ifndef Tcl_GetBooleanFromObj_TCL_DECLARED
#define Tcl_GetBooleanFromObj_TCL_DECLARED
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *intPtr);
#endif
#ifndef Tcl_GetByteArrayFromObj_TCL_DECLARED
#define Tcl_GetByteArrayFromObj_TCL_DECLARED
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
				int *lengthPtr);
#endif







|





|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/* 30 */
EXTERN void		TclFreeObj(Tcl_Obj *objPtr);
#endif
#ifndef Tcl_GetBoolean_TCL_DECLARED
#define Tcl_GetBoolean_TCL_DECLARED
/* 31 */
EXTERN int		Tcl_GetBoolean(Tcl_Interp *interp, CONST char *src,
				int *boolPtr);
#endif
#ifndef Tcl_GetBooleanFromObj_TCL_DECLARED
#define Tcl_GetBooleanFromObj_TCL_DECLARED
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *boolPtr);
#endif
#ifndef Tcl_GetByteArrayFromObj_TCL_DECLARED
#define Tcl_GetByteArrayFromObj_TCL_DECLARED
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
				int *lengthPtr);
#endif
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
EXTERN int		Tcl_ListObjReplace(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int first, int count,
				int objc, Tcl_Obj *CONST objv[]);
#endif
#ifndef Tcl_NewBooleanObj_TCL_DECLARED
#define Tcl_NewBooleanObj_TCL_DECLARED
/* 49 */
EXTERN Tcl_Obj *	Tcl_NewBooleanObj(int intValue);
#endif
#ifndef Tcl_NewByteArrayObj_TCL_DECLARED
#define Tcl_NewByteArrayObj_TCL_DECLARED
/* 50 */
EXTERN Tcl_Obj *	Tcl_NewByteArrayObj(CONST unsigned char *bytes,
				int length);
#endif







|







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
EXTERN int		Tcl_ListObjReplace(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int first, int count,
				int objc, Tcl_Obj *CONST objv[]);
#endif
#ifndef Tcl_NewBooleanObj_TCL_DECLARED
#define Tcl_NewBooleanObj_TCL_DECLARED
/* 49 */
EXTERN Tcl_Obj *	Tcl_NewBooleanObj(int boolValue);
#endif
#ifndef Tcl_NewByteArrayObj_TCL_DECLARED
#define Tcl_NewByteArrayObj_TCL_DECLARED
/* 50 */
EXTERN Tcl_Obj *	Tcl_NewByteArrayObj(CONST unsigned char *bytes,
				int length);
#endif
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
#define Tcl_NewStringObj_TCL_DECLARED
/* 56 */
EXTERN Tcl_Obj *	Tcl_NewStringObj(CONST char *bytes, int length);
#endif
#ifndef Tcl_SetBooleanObj_TCL_DECLARED
#define Tcl_SetBooleanObj_TCL_DECLARED
/* 57 */
EXTERN void		Tcl_SetBooleanObj(Tcl_Obj *objPtr, int intValue);
#endif
#ifndef Tcl_SetByteArrayLength_TCL_DECLARED
#define Tcl_SetByteArrayLength_TCL_DECLARED
/* 58 */
EXTERN unsigned char *	Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int numBytes);
#endif
#ifndef Tcl_SetByteArrayObj_TCL_DECLARED
#define Tcl_SetByteArrayObj_TCL_DECLARED
/* 59 */
EXTERN void		Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
				CONST unsigned char *bytes, int numBytes);
#endif
#ifndef Tcl_SetDoubleObj_TCL_DECLARED
#define Tcl_SetDoubleObj_TCL_DECLARED
/* 60 */
EXTERN void		Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
#endif
#ifndef Tcl_SetIntObj_TCL_DECLARED







|




|





|







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
#define Tcl_NewStringObj_TCL_DECLARED
/* 56 */
EXTERN Tcl_Obj *	Tcl_NewStringObj(CONST char *bytes, int length);
#endif
#ifndef Tcl_SetBooleanObj_TCL_DECLARED
#define Tcl_SetBooleanObj_TCL_DECLARED
/* 57 */
EXTERN void		Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue);
#endif
#ifndef Tcl_SetByteArrayLength_TCL_DECLARED
#define Tcl_SetByteArrayLength_TCL_DECLARED
/* 58 */
EXTERN unsigned char *	Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length);
#endif
#ifndef Tcl_SetByteArrayObj_TCL_DECLARED
#define Tcl_SetByteArrayObj_TCL_DECLARED
/* 59 */
EXTERN void		Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
				CONST unsigned char *bytes, int length);
#endif
#ifndef Tcl_SetDoubleObj_TCL_DECLARED
#define Tcl_SetDoubleObj_TCL_DECLARED
/* 60 */
EXTERN void		Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
#endif
#ifndef Tcl_SetIntObj_TCL_DECLARED
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
/* 85 */
EXTERN int		Tcl_ConvertCountedElement(CONST char *src,
				int length, char *dst, int flags);
#endif
#ifndef Tcl_CreateAlias_TCL_DECLARED
#define Tcl_CreateAlias_TCL_DECLARED
/* 86 */
EXTERN int		Tcl_CreateAlias(Tcl_Interp *childInterp,
				CONST char *childCmd, Tcl_Interp *target,
				CONST char *targetCmd, int argc,
				CONST84 char *CONST *argv);
#endif
#ifndef Tcl_CreateAliasObj_TCL_DECLARED
#define Tcl_CreateAliasObj_TCL_DECLARED
/* 87 */
EXTERN int		Tcl_CreateAliasObj(Tcl_Interp *childInterp,
				CONST char *childCmd, Tcl_Interp *target,
				CONST char *targetCmd, int objc,
				Tcl_Obj *CONST objv[]);
#endif
#ifndef Tcl_CreateChannel_TCL_DECLARED
#define Tcl_CreateChannel_TCL_DECLARED
/* 88 */
EXTERN Tcl_Channel	Tcl_CreateChannel(Tcl_ChannelType *typePtr,







|
|






|
|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
/* 85 */
EXTERN int		Tcl_ConvertCountedElement(CONST char *src,
				int length, char *dst, int flags);
#endif
#ifndef Tcl_CreateAlias_TCL_DECLARED
#define Tcl_CreateAlias_TCL_DECLARED
/* 86 */
EXTERN int		Tcl_CreateAlias(Tcl_Interp *slave,
				CONST char *slaveCmd, Tcl_Interp *target,
				CONST char *targetCmd, int argc,
				CONST84 char *CONST *argv);
#endif
#ifndef Tcl_CreateAliasObj_TCL_DECLARED
#define Tcl_CreateAliasObj_TCL_DECLARED
/* 87 */
EXTERN int		Tcl_CreateAliasObj(Tcl_Interp *slave,
				CONST char *slaveCmd, Tcl_Interp *target,
				CONST char *targetCmd, int objc,
				Tcl_Obj *CONST objv[]);
#endif
#ifndef Tcl_CreateChannel_TCL_DECLARED
#define Tcl_CreateChannel_TCL_DECLARED
/* 88 */
EXTERN Tcl_Channel	Tcl_CreateChannel(Tcl_ChannelType *typePtr,
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
				CONST char *cmdName, Tcl_ObjCmdProc *proc,
				ClientData clientData,
				Tcl_CmdDeleteProc *deleteProc);
#endif
#ifndef Tcl_CreateSlave_TCL_DECLARED
#define Tcl_CreateSlave_TCL_DECLARED
/* 97 */
EXTERN Tcl_Interp *	Tcl_CreateSlave(Tcl_Interp *interp, CONST char *name,
				int isSafe);
#endif
#ifndef Tcl_CreateTimerHandler_TCL_DECLARED
#define Tcl_CreateTimerHandler_TCL_DECLARED
/* 98 */
EXTERN Tcl_TimerToken	Tcl_CreateTimerHandler(int milliseconds,
				Tcl_TimerProc *proc, ClientData clientData);
#endif







|
|







617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
				CONST char *cmdName, Tcl_ObjCmdProc *proc,
				ClientData clientData,
				Tcl_CmdDeleteProc *deleteProc);
#endif
#ifndef Tcl_CreateSlave_TCL_DECLARED
#define Tcl_CreateSlave_TCL_DECLARED
/* 97 */
EXTERN Tcl_Interp *	Tcl_CreateSlave(Tcl_Interp *interp,
				CONST char *slaveName, int isSafe);
#endif
#ifndef Tcl_CreateTimerHandler_TCL_DECLARED
#define Tcl_CreateTimerHandler_TCL_DECLARED
/* 98 */
EXTERN Tcl_TimerToken	Tcl_CreateTimerHandler(int milliseconds,
				Tcl_TimerProc *proc, ClientData clientData);
#endif
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
#define Tcl_GetHostName_TCL_DECLARED
/* 162 */
EXTERN CONST84_RETURN char * Tcl_GetHostName(void);
#endif
#ifndef Tcl_GetInterpPath_TCL_DECLARED
#define Tcl_GetInterpPath_TCL_DECLARED
/* 163 */
EXTERN int		Tcl_GetInterpPath(Tcl_Interp *interp,
				Tcl_Interp *childInterp);
#endif
#ifndef Tcl_GetMaster_TCL_DECLARED
#define Tcl_GetMaster_TCL_DECLARED
/* 164 */
EXTERN Tcl_Interp *	Tcl_GetMaster(Tcl_Interp *interp);
#endif
#ifndef Tcl_GetNameOfExecutable_TCL_DECLARED







|
|







995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
#define Tcl_GetHostName_TCL_DECLARED
/* 162 */
EXTERN CONST84_RETURN char * Tcl_GetHostName(void);
#endif
#ifndef Tcl_GetInterpPath_TCL_DECLARED
#define Tcl_GetInterpPath_TCL_DECLARED
/* 163 */
EXTERN int		Tcl_GetInterpPath(Tcl_Interp *askInterp,
				Tcl_Interp *slaveInterp);
#endif
#ifndef Tcl_GetMaster_TCL_DECLARED
#define Tcl_GetMaster_TCL_DECLARED
/* 164 */
EXTERN Tcl_Interp *	Tcl_GetMaster(Tcl_Interp *interp);
#endif
#ifndef Tcl_GetNameOfExecutable_TCL_DECLARED
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
				int permissions);
#endif
#ifndef Tcl_OpenTcpClient_TCL_DECLARED
#define Tcl_OpenTcpClient_TCL_DECLARED
/* 199 */
EXTERN Tcl_Channel	Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
				CONST char *address, CONST char *myaddr,
				int myport, int flags);
#endif
#ifndef Tcl_OpenTcpServer_TCL_DECLARED
#define Tcl_OpenTcpServer_TCL_DECLARED
/* 200 */
EXTERN Tcl_Channel	Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
				CONST char *host,
				Tcl_TcpAcceptProc *acceptProc,







|







1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
				int permissions);
#endif
#ifndef Tcl_OpenTcpClient_TCL_DECLARED
#define Tcl_OpenTcpClient_TCL_DECLARED
/* 199 */
EXTERN Tcl_Channel	Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
				CONST char *address, CONST char *myaddr,
				int myport, int async);
#endif
#ifndef Tcl_OpenTcpServer_TCL_DECLARED
#define Tcl_OpenTcpServer_TCL_DECLARED
/* 200 */
EXTERN Tcl_Channel	Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
				CONST char *host,
				Tcl_TcpAcceptProc *acceptProc,
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
/* Slot 623 is reserved */
/* Slot 624 is reserved */
/* Slot 625 is reserved */
/* Slot 626 is reserved */
/* Slot 627 is reserved */
/* Slot 628 is reserved */
/* Slot 629 is reserved */
/* Slot 630 is reserved */
/* Slot 631 is reserved */
/* Slot 632 is reserved */
/* Slot 633 is reserved */
/* Slot 634 is reserved */
/* Slot 635 is reserved */
/* Slot 636 is reserved */
/* Slot 637 is reserved */
/* Slot 638 is reserved */
/* Slot 639 is reserved */
/* Slot 640 is reserved */
/* Slot 641 is reserved */
/* Slot 642 is reserved */
/* Slot 643 is reserved */
/* Slot 644 is reserved */
/* Slot 645 is reserved */
/* Slot 646 is reserved */
/* Slot 647 is reserved */
/* Slot 648 is reserved */
/* Slot 649 is reserved */
/* Slot 650 is reserved */
/* Slot 651 is reserved */
/* Slot 652 is reserved */
/* Slot 653 is reserved */
/* Slot 654 is reserved */
/* Slot 655 is reserved */
/* Slot 656 is reserved */
/* Slot 657 is reserved */
/* Slot 658 is reserved */
/* Slot 659 is reserved */
/* Slot 660 is reserved */
/* Slot 661 is reserved */
/* Slot 662 is reserved */
/* Slot 663 is reserved */
/* Slot 664 is reserved */
/* Slot 665 is reserved */
/* Slot 666 is reserved */
/* Slot 667 is reserved */
/* Slot 668 is reserved */
/* Slot 669 is reserved */
/* Slot 670 is reserved */
/* Slot 671 is reserved */
/* Slot 672 is reserved */
/* Slot 673 is reserved */
/* Slot 674 is reserved */
/* Slot 675 is reserved */
/* Slot 676 is reserved */
/* Slot 677 is reserved */
/* Slot 678 is reserved */
/* Slot 679 is reserved */
/* Slot 680 is reserved */
/* Slot 681 is reserved */
/* Slot 682 is reserved */
/* Slot 683 is reserved */
/* Slot 684 is reserved */
/* Slot 685 is reserved */
/* Slot 686 is reserved */
#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 687 */
EXTERN void		TclUnusedStubEntry(void);
#endif

typedef struct TclStubHooks {
    struct TclPlatStubs *tclPlatStubs;
    struct TclIntStubs *tclIntStubs;
    struct TclIntPlatStubs *tclIntPlatStubs;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|







3458
3459
3460
3461
3462
3463
3464

























































3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
/* Slot 623 is reserved */
/* Slot 624 is reserved */
/* Slot 625 is reserved */
/* Slot 626 is reserved */
/* Slot 627 is reserved */
/* Slot 628 is reserved */
/* Slot 629 is reserved */

























































#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 630 */
EXTERN void		TclUnusedStubEntry(void);
#endif

typedef struct TclStubHooks {
    struct TclPlatStubs *tclPlatStubs;
    struct TclIntStubs *tclIntStubs;
    struct TclIntPlatStubs *tclIntPlatStubs;
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
    Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, CONST char *file, int line); /* 24 */
    Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *CONST *objv, CONST char *file, int line); /* 25 */
    Tcl_Obj * (*tcl_DbNewLongObj) (long longValue, CONST char *file, int line); /* 26 */
    Tcl_Obj * (*tcl_DbNewObj) (CONST char *file, int line); /* 27 */
    Tcl_Obj * (*tcl_DbNewStringObj) (CONST char *bytes, int length, CONST char *file, int line); /* 28 */
    Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */
    void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
    int (*tcl_GetBoolean) (Tcl_Interp *interp, CONST char *src, int *intPtr); /* 31 */
    int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 32 */
    unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
    int (*tcl_GetDouble) (Tcl_Interp *interp, CONST char *src, double *doublePtr); /* 34 */
    int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
    int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char **tablePtr, CONST char *msg, int flags, int *indexPtr); /* 36 */
    int (*tcl_GetInt) (Tcl_Interp *interp, CONST char *src, int *intPtr); /* 37 */
    int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
    int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
    Tcl_ObjType * (*tcl_GetObjType) (CONST char *typeName); /* 40 */
    char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
    void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
    int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
    int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
    int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
    int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */
    int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
    int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *CONST objv[]); /* 48 */
    Tcl_Obj * (*tcl_NewBooleanObj) (int intValue); /* 49 */
    Tcl_Obj * (*tcl_NewByteArrayObj) (CONST unsigned char *bytes, int length); /* 50 */
    Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
    Tcl_Obj * (*tcl_NewIntObj) (int intValue); /* 52 */
    Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *CONST objv[]); /* 53 */
    Tcl_Obj * (*tcl_NewLongObj) (long longValue); /* 54 */
    Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
    Tcl_Obj * (*tcl_NewStringObj) (CONST char *bytes, int length); /* 56 */
    void (*tcl_SetBooleanObj) (Tcl_Obj *objPtr, int intValue); /* 57 */
    unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, int numBytes); /* 58 */
    void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, CONST unsigned char *bytes, int numBytes); /* 59 */
    void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
    void (*tcl_SetIntObj) (Tcl_Obj *objPtr, int intValue); /* 61 */
    void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *CONST objv[]); /* 62 */
    void (*tcl_SetLongObj) (Tcl_Obj *objPtr, long longValue); /* 63 */
    void (*tcl_SetObjLength) (Tcl_Obj *objPtr, int length); /* 64 */
    void (*tcl_SetStringObj) (Tcl_Obj *objPtr, CONST char *bytes, int length); /* 65 */
    void (*tcl_AddErrorInfo) (Tcl_Interp *interp, CONST char *message); /* 66 */







|
|
















|







|
|
|







3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
    Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, CONST char *file, int line); /* 24 */
    Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *CONST *objv, CONST char *file, int line); /* 25 */
    Tcl_Obj * (*tcl_DbNewLongObj) (long longValue, CONST char *file, int line); /* 26 */
    Tcl_Obj * (*tcl_DbNewObj) (CONST char *file, int line); /* 27 */
    Tcl_Obj * (*tcl_DbNewStringObj) (CONST char *bytes, int length, CONST char *file, int line); /* 28 */
    Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */
    void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
    int (*tcl_GetBoolean) (Tcl_Interp *interp, CONST char *src, int *boolPtr); /* 31 */
    int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */
    unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
    int (*tcl_GetDouble) (Tcl_Interp *interp, CONST char *src, double *doublePtr); /* 34 */
    int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
    int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char **tablePtr, CONST char *msg, int flags, int *indexPtr); /* 36 */
    int (*tcl_GetInt) (Tcl_Interp *interp, CONST char *src, int *intPtr); /* 37 */
    int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
    int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
    Tcl_ObjType * (*tcl_GetObjType) (CONST char *typeName); /* 40 */
    char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
    void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
    int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
    int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
    int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
    int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */
    int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
    int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *CONST objv[]); /* 48 */
    Tcl_Obj * (*tcl_NewBooleanObj) (int boolValue); /* 49 */
    Tcl_Obj * (*tcl_NewByteArrayObj) (CONST unsigned char *bytes, int length); /* 50 */
    Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
    Tcl_Obj * (*tcl_NewIntObj) (int intValue); /* 52 */
    Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *CONST objv[]); /* 53 */
    Tcl_Obj * (*tcl_NewLongObj) (long longValue); /* 54 */
    Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
    Tcl_Obj * (*tcl_NewStringObj) (CONST char *bytes, int length); /* 56 */
    void (*tcl_SetBooleanObj) (Tcl_Obj *objPtr, int boolValue); /* 57 */
    unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, int length); /* 58 */
    void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, CONST unsigned char *bytes, int length); /* 59 */
    void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
    void (*tcl_SetIntObj) (Tcl_Obj *objPtr, int intValue); /* 61 */
    void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *CONST objv[]); /* 62 */
    void (*tcl_SetLongObj) (Tcl_Obj *objPtr, long longValue); /* 63 */
    void (*tcl_SetObjLength) (Tcl_Obj *objPtr, int length); /* 64 */
    void (*tcl_SetStringObj) (Tcl_Obj *objPtr, CONST char *bytes, int length); /* 65 */
    void (*tcl_AddErrorInfo) (Tcl_Interp *interp, CONST char *message); /* 66 */
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
    void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */
    void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */
    int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
    int (*tcl_CommandComplete) (CONST char *cmd); /* 82 */
    char * (*tcl_Concat) (int argc, CONST84 char *CONST *argv); /* 83 */
    int (*tcl_ConvertElement) (CONST char *src, char *dst, int flags); /* 84 */
    int (*tcl_ConvertCountedElement) (CONST char *src, int length, char *dst, int flags); /* 85 */
    int (*tcl_CreateAlias) (Tcl_Interp *childInterp, CONST char *childCmd, Tcl_Interp *target, CONST char *targetCmd, int argc, CONST84 char *CONST *argv); /* 86 */
    int (*tcl_CreateAliasObj) (Tcl_Interp *childInterp, CONST char *childCmd, Tcl_Interp *target, CONST char *targetCmd, int objc, Tcl_Obj *CONST objv[]); /* 87 */
    Tcl_Channel (*tcl_CreateChannel) (Tcl_ChannelType *typePtr, CONST char *chanName, ClientData instanceData, int mask); /* 88 */
    void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 89 */
    void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 90 */
    Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */
    void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 92 */
    void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 93 */
    Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */
    void (*tcl_CreateMathFunc) (Tcl_Interp *interp, CONST char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */
    Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */
    Tcl_Interp * (*tcl_CreateSlave) (Tcl_Interp *interp, CONST char *name, int isSafe); /* 97 */
    Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 98 */
    Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData); /* 99 */
    void (*tcl_DeleteAssocData) (Tcl_Interp *interp, CONST char *name); /* 100 */
    void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData); /* 101 */
    void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 102 */
    int (*tcl_DeleteCommand) (Tcl_Interp *interp, CONST char *cmdName); /* 103 */
    int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */







|
|









|







3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
    void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */
    void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */
    int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
    int (*tcl_CommandComplete) (CONST char *cmd); /* 82 */
    char * (*tcl_Concat) (int argc, CONST84 char *CONST *argv); /* 83 */
    int (*tcl_ConvertElement) (CONST char *src, char *dst, int flags); /* 84 */
    int (*tcl_ConvertCountedElement) (CONST char *src, int length, char *dst, int flags); /* 85 */
    int (*tcl_CreateAlias) (Tcl_Interp *slave, CONST char *slaveCmd, Tcl_Interp *target, CONST char *targetCmd, int argc, CONST84 char *CONST *argv); /* 86 */
    int (*tcl_CreateAliasObj) (Tcl_Interp *slave, CONST char *slaveCmd, Tcl_Interp *target, CONST char *targetCmd, int objc, Tcl_Obj *CONST objv[]); /* 87 */
    Tcl_Channel (*tcl_CreateChannel) (Tcl_ChannelType *typePtr, CONST char *chanName, ClientData instanceData, int mask); /* 88 */
    void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 89 */
    void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 90 */
    Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */
    void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 92 */
    void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 93 */
    Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */
    void (*tcl_CreateMathFunc) (Tcl_Interp *interp, CONST char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */
    Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */
    Tcl_Interp * (*tcl_CreateSlave) (Tcl_Interp *interp, CONST char *slaveName, int isSafe); /* 97 */
    Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 98 */
    Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData); /* 99 */
    void (*tcl_DeleteAssocData) (Tcl_Interp *interp, CONST char *name); /* 100 */
    void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData); /* 101 */
    void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 102 */
    int (*tcl_DeleteCommand) (Tcl_Interp *interp, CONST char *cmdName); /* 103 */
    int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
    CONST84_RETURN char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
    int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, CONST char *optionName, Tcl_DString *dsPtr); /* 157 */
    Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */
    int (*tcl_GetCommandInfo) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */
    CONST84_RETURN char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
    int (*tcl_GetErrno) (void); /* 161 */
    CONST84_RETURN char * (*tcl_GetHostName) (void); /* 162 */
    int (*tcl_GetInterpPath) (Tcl_Interp *interp, Tcl_Interp *childInterp); /* 163 */
    Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
    CONST char * (*tcl_GetNameOfExecutable) (void); /* 165 */
    Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
    int (*tcl_GetOpenFile) (Tcl_Interp *interp, CONST char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */







|







3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
    CONST84_RETURN char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
    int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, CONST char *optionName, Tcl_DString *dsPtr); /* 157 */
    Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */
    int (*tcl_GetCommandInfo) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */
    CONST84_RETURN char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
    int (*tcl_GetErrno) (void); /* 161 */
    CONST84_RETURN char * (*tcl_GetHostName) (void); /* 162 */
    int (*tcl_GetInterpPath) (Tcl_Interp *askInterp, Tcl_Interp *slaveInterp); /* 163 */
    Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
    CONST char * (*tcl_GetNameOfExecutable) (void); /* 165 */
    Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
    int (*tcl_GetOpenFile) (Tcl_Interp *interp, CONST char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
#endif /* UNIX */
#if defined(__WIN32__) /* WIN */
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
    char * (*tcl_Merge) (int argc, CONST84 char *CONST *argv); /* 192 */
    Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */
    void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */
    Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */
    Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */
    Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 197 */
    Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, CONST char *fileName, CONST char *modeString, int permissions); /* 198 */
    Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, CONST char *address, CONST char *myaddr, int myport, int flags); /* 199 */
    Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, CONST char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 200 */
    void (*tcl_Preserve) (ClientData data); /* 201 */
    void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */
    int (*tcl_PutEnv) (CONST char *assignment); /* 203 */
    CONST84_RETURN char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
    void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */
    int (*tcl_Read) (Tcl_Channel chan, char *bufPtr, int toRead); /* 206 */







|







3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
    char * (*tcl_Merge) (int argc, CONST84 char *CONST *argv); /* 192 */
    Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */
    void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */
    Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */
    Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */
    Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 197 */
    Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, CONST char *fileName, CONST char *modeString, int permissions); /* 198 */
    Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, CONST char *address, CONST char *myaddr, int myport, int async); /* 199 */
    Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, CONST char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 200 */
    void (*tcl_Preserve) (ClientData data); /* 201 */
    void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */
    int (*tcl_PutEnv) (CONST char *assignment); /* 203 */
    CONST84_RETURN char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
    void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */
    int (*tcl_Read) (Tcl_Channel chan, char *bufPtr, int toRead); /* 206 */
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
    VOID *reserved623;
    VOID *reserved624;
    VOID *reserved625;
    VOID *reserved626;
    VOID *reserved627;
    VOID *reserved628;
    VOID *reserved629;
    VOID *reserved630;
    VOID *reserved631;
    VOID *reserved632;
    VOID *reserved633;
    VOID *reserved634;
    VOID *reserved635;
    VOID *reserved636;
    VOID *reserved637;
    VOID *reserved638;
    VOID *reserved639;
    VOID *reserved640;
    VOID *reserved641;
    VOID *reserved642;
    VOID *reserved643;
    VOID *reserved644;
    VOID *reserved645;
    VOID *reserved646;
    VOID *reserved647;
    VOID *reserved648;
    VOID *reserved649;
    VOID *reserved650;
    VOID *reserved651;
    VOID *reserved652;
    VOID *reserved653;
    VOID *reserved654;
    VOID *reserved655;
    VOID *reserved656;
    VOID *reserved657;
    VOID *reserved658;
    VOID *reserved659;
    VOID *reserved660;
    VOID *reserved661;
    VOID *reserved662;
    VOID *reserved663;
    VOID *reserved664;
    VOID *reserved665;
    VOID *reserved666;
    VOID *reserved667;
    VOID *reserved668;
    VOID *reserved669;
    VOID *reserved670;
    VOID *reserved671;
    VOID *reserved672;
    VOID *reserved673;
    VOID *reserved674;
    VOID *reserved675;
    VOID *reserved676;
    VOID *reserved677;
    VOID *reserved678;
    VOID *reserved679;
    VOID *reserved680;
    VOID *reserved681;
    VOID *reserved682;
    VOID *reserved683;
    VOID *reserved684;
    VOID *reserved685;
    VOID *reserved686;
    void (*tclUnusedStubEntry) (void); /* 687 */
} TclStubs;

extern TclStubs *tclStubsPtr;

#ifdef __cplusplus
}
#endif







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







4128
4129
4130
4131
4132
4133
4134

























































4135
4136
4137
4138
4139
4140
4141
4142
    VOID *reserved623;
    VOID *reserved624;
    VOID *reserved625;
    VOID *reserved626;
    VOID *reserved627;
    VOID *reserved628;
    VOID *reserved629;

























































    void (*tclUnusedStubEntry) (void); /* 630 */
} TclStubs;

extern TclStubs *tclStubsPtr;

#ifdef __cplusplus
}
#endif
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
/* Slot 623 is reserved */
/* Slot 624 is reserved */
/* Slot 625 is reserved */
/* Slot 626 is reserved */
/* Slot 627 is reserved */
/* Slot 628 is reserved */
/* Slot 629 is reserved */
/* Slot 630 is reserved */
/* Slot 631 is reserved */
/* Slot 632 is reserved */
/* Slot 633 is reserved */
/* Slot 634 is reserved */
/* Slot 635 is reserved */
/* Slot 636 is reserved */
/* Slot 637 is reserved */
/* Slot 638 is reserved */
/* Slot 639 is reserved */
/* Slot 640 is reserved */
/* Slot 641 is reserved */
/* Slot 642 is reserved */
/* Slot 643 is reserved */
/* Slot 644 is reserved */
/* Slot 645 is reserved */
/* Slot 646 is reserved */
/* Slot 647 is reserved */
/* Slot 648 is reserved */
/* Slot 649 is reserved */
/* Slot 650 is reserved */
/* Slot 651 is reserved */
/* Slot 652 is reserved */
/* Slot 653 is reserved */
/* Slot 654 is reserved */
/* Slot 655 is reserved */
/* Slot 656 is reserved */
/* Slot 657 is reserved */
/* Slot 658 is reserved */
/* Slot 659 is reserved */
/* Slot 660 is reserved */
/* Slot 661 is reserved */
/* Slot 662 is reserved */
/* Slot 663 is reserved */
/* Slot 664 is reserved */
/* Slot 665 is reserved */
/* Slot 666 is reserved */
/* Slot 667 is reserved */
/* Slot 668 is reserved */
/* Slot 669 is reserved */
/* Slot 670 is reserved */
/* Slot 671 is reserved */
/* Slot 672 is reserved */
/* Slot 673 is reserved */
/* Slot 674 is reserved */
/* Slot 675 is reserved */
/* Slot 676 is reserved */
/* Slot 677 is reserved */
/* Slot 678 is reserved */
/* Slot 679 is reserved */
/* Slot 680 is reserved */
/* Slot 681 is reserved */
/* Slot 682 is reserved */
/* Slot 683 is reserved */
/* Slot 684 is reserved */
/* Slot 685 is reserved */
/* Slot 686 is reserved */
#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclStubsPtr->tclUnusedStubEntry) /* 687 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TclUnusedStubEntry







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|







6531
6532
6533
6534
6535
6536
6537

























































6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
/* Slot 623 is reserved */
/* Slot 624 is reserved */
/* Slot 625 is reserved */
/* Slot 626 is reserved */
/* Slot 627 is reserved */
/* Slot 628 is reserved */
/* Slot 629 is reserved */

























































#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclStubsPtr->tclUnusedStubEntry) /* 630 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TclUnusedStubEntry

Changes to generic/tclDictObj.c.

164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
 *
 * Note that this type of hash table is *only* suitable for direct use in
 * *this* file. Everything else should use the dict iterator API.
 */

static Tcl_HashKeyType chainHashType = {
    TCL_HASH_KEY_TYPE_VERSION,
    TCL_HASH_KEY_DIRECT_COMPARE,        /* allows compare keys by pointers */

    TclHashObjKey,
    TclCompareObjKeys,
    AllocChainEntry,
    TclFreeObjEntry
};

/***** START OF FUNCTIONS IMPLEMENTING DICT CORE API *****/







<
>







164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
 *
 * Note that this type of hash table is *only* suitable for direct use in
 * *this* file. Everything else should use the dict iterator API.
 */

static Tcl_HashKeyType chainHashType = {
    TCL_HASH_KEY_TYPE_VERSION,

    0,
    TclHashObjKey,
    TclCompareObjKeys,
    AllocChainEntry,
    TclFreeObjEntry
};

/***** START OF FUNCTIONS IMPLEMENTING DICT CORE API *****/
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
		 * Force loop termination by calling Tcl_DictObjDone; this
		 * makes the next Tcl_DictObjNext say there is nothing more to
		 * do.
		 */

		Tcl_ResetResult(interp);
		Tcl_DictObjDone(&search);
	    /* FALLTHRU */
	    case TCL_CONTINUE:
		result = TCL_OK;
		break;
	    case TCL_ERROR:
		Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			"\n    (\"dict filter\" script line %d)",
			interp->errorLine));







<







2768
2769
2770
2771
2772
2773
2774

2775
2776
2777
2778
2779
2780
2781
		 * Force loop termination by calling Tcl_DictObjDone; this
		 * makes the next Tcl_DictObjNext say there is nothing more to
		 * do.
		 */

		Tcl_ResetResult(interp);
		Tcl_DictObjDone(&search);

	    case TCL_CONTINUE:
		result = TCL_OK;
		break;
	    case TCL_ERROR:
		Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			"\n    (\"dict filter\" script line %d)",
			interp->errorLine));

Changes to generic/tclEncoding.c.

2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367

2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    char *dstEnd, *dstStart;
    int result, numChars;
    unsigned short ch;

    result = TCL_OK;
    if ((srcLen & 1) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;

    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	/*
	 * Special case for 1-byte utf chars for speed.  Make sure we
	 * work with Tcl_UniChar-size data.
	 */
	ch = *(unsigned short *)src;
	if (ch && ch < 0x80) {
	    *dst++ = (ch & 0xFF);
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src += sizeof(unsigned short);
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}







|


|

|
>

















|





|







2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    char *dstEnd, *dstStart;
    int result, numChars;
    Tcl_UniChar ch;

    result = TCL_OK;
    if ((srcLen % sizeof(Tcl_UniChar)) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen /= sizeof(Tcl_UniChar);
	srcLen *= sizeof(Tcl_UniChar);
    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	/*
	 * Special case for 1-byte utf chars for speed.  Make sure we
	 * work with Tcl_UniChar-size data.
	 */
	ch = *(Tcl_UniChar *)src;
	if (ch && ch < 0x80) {
	    *dst++ = (ch & 0xFF);
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src += sizeof(Tcl_UniChar);
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}
2467
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478


2479
2480
2481
2482
2483
2484
2485
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
        }
	src += TclUtfToUniChar(src, &ch);
#if TCL_UTF_MAX > 3

	if (ch & ~0xFFFF) {
	    ch = 0xFFFD;
	}
#endif


#ifdef WORDS_BIGENDIAN
	*dst++ = (ch >> 8);
	*dst++ = (ch & 0xFF);
#else
	*dst++ = (ch & 0xFF);
	*dst++ = (ch >> 8);
#endif







<
>
|
|
<
<
>
>







2468
2469
2470
2471
2472
2473
2474

2475
2476
2477


2478
2479
2480
2481
2482
2483
2484
2485
2486
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
        }
	src += TclUtfToUniChar(src, &ch);

	/*
	 * Need to handle this in a way that won't cause misalignment
	 * by casting dst to a Tcl_UniChar. [Bug 1122671]


	 * XXX: This hard-codes the assumed size of Tcl_UniChar as 2.
	 */
#ifdef WORDS_BIGENDIAN
	*dst++ = (ch >> 8);
	*dst++ = (ch & 0xFF);
#else
	*dst++ = (ch & 0xFF);
	*dst++ = (ch >> 8);
#endif
2676
2677
2678
2679
2680
2681
2682




2683
2684
2685
2686
2687
2688
2689
2690
2691

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	len = TclUtfToUniChar(src, &ch);

#if TCL_UTF_MAX > 3




	/* Unicode chars > +U0FFFF cannot be represented in any table encoding */
	if (ch & ~0xFFFF) {
	    word = 0;
	} else
#endif
	    word = fromUnicode[(ch >> 8)][ch & 0xff];

	if ((word == 0) && (ch != 0)) {
	    if (flags & TCL_ENCODING_STOPONERROR) {







>
>
>
>
|
|







2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	len = TclUtfToUniChar(src, &ch);

#if TCL_UTF_MAX > 3
	/*
	 * This prevents a crash condition. More evaluation is required for
	 * full support of int Tcl_UniChar. [Bug 1004065]
	 */

	if (ch & 0xffff0000) {
	    word = 0;
	} else
#endif
	    word = fromUnicode[(ch >> 8)][ch & 0xff];

	if ((word == 0) && (ch != 0)) {
	    if (flags & TCL_ENCODING_STOPONERROR) {

Changes to generic/tclExecute.c.

1342
1343
1344
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354



1355
1356
1357

1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1370

1371















1372
1373
1374
1375
1376
1377
1378
    }
    objPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileObj --
 *
 *  This procedure compiles the script contained in a Tcl_Obj.

 *
 * Results:
 *  A pointer to the corresponding ByteCode, never NULL.



 *
 * Side effects:
 *  The object is shimmered to bytecode type.

 *
 *----------------------------------------------------------------------
 */

ByteCode *

TclCompileObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    register Interp *iPtr = (Interp *) interp;
    register ByteCode *codePtr;	/* Tcl Internal type of bytecode. */

    Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;
















    /*
     * If the object is not already of tclByteCodeType, compile it (and reset
     * the compilation flags in the interpreter; this should be done after any
     * compilation). Otherwise, check that it is "fresh" enough.
     */








|

|
>


<
>
>
>


<
>




<
>
|







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357
1358
1359

1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
    }
    objPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompEvalObj --
 *
 *	This procedure evaluates the script contained in a Tcl_Obj by first
 *	compiling it and then passing it to TclExecuteByteCode.
 *
 * Results:

 *	The return value is one of the return codes defined in tcl.h (such as
 *	TCL_OK), and interp->objResultPtr refers to a Tcl object that either
 *	contains the result of executing the code or an error message.
 *
 * Side effects:

 *	Almost certainly, depending on the ByteCode's instructions.
 *
 *----------------------------------------------------------------------
 */


int
TclCompEvalObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    register Interp *iPtr = (Interp *) interp;
    register ByteCode *codePtr;	/* Tcl Internal type of bytecode. */
    int result;
    Namespace *namespacePtr;

    /*
     * Check that the interpreter is ready to execute scripts. Note that we
     * manage the interp's runlevel here: it is a small white lie (maybe), but
     * saves a ++/-- pair at each invocation. Amazingly enough, the impact on
     * performance is noticeable.
     */

    iPtr->numLevels++;
    if (TclInterpReady(interp) == TCL_ERROR) {
	result = TCL_ERROR;
	goto done;
    }

    namespacePtr = iPtr->varFramePtr->nsPtr;

    /*
     * If the object is not already of tclByteCodeType, compile it (and reset
     * the compilation flags in the interpreter; this should be done after any
     * compilation). Otherwise, check that it is "fresh" enough.
     */

1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
	 */

	codePtr = (ByteCode *) objPtr->internalRep.twoPtrValue.ptr1;
	if (((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != namespacePtr)
		|| (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
	    if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
		goto recompileObj;
	    }
	    if ((Interp *) *codePtr->interpHandle != iPtr) {
		Tcl_Panic("Tcl_EvalObj: compiled script jumped interps");
	    }
	    codePtr->compileEpoch = iPtr->compileEpoch;
	}

	/*
	 * Check that any compiled locals do refer to the current proc
	 * environment! If not, recompile.
	 */

	if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED) &&
		(codePtr->procPtr == NULL) &&
		(codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)){
	    goto recompileObj;

	}

	/*
	 * #280.
	 * Literal sharing fix. This part of the fix is not required by 8.4
	 * because it eval-directs any literals, so just saving the argument
	 * locations per command in bytecode is enough, embedded 'eval'







|
<
<
|
|
|
|
<
|
|
<
|
|

<
|
<
|
>







1414
1415
1416
1417
1418
1419
1420
1421


1422
1423
1424
1425

1426
1427

1428
1429
1430

1431

1432
1433
1434
1435
1436
1437
1438
1439
1440
	 */

	codePtr = (ByteCode *) objPtr->internalRep.twoPtrValue.ptr1;
	if (((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != namespacePtr)
		|| (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
	    if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {


		if ((Interp *) *codePtr->interpHandle != iPtr) {
		    Tcl_Panic("Tcl_EvalObj: compiled script jumped interps");
		}
		codePtr->compileEpoch = iPtr->compileEpoch;

	    } else {
		/*

		 * This byteCode is invalid: free it and recompile.
		 */


		objPtr->typePtr->freeIntRepProc(objPtr);

		goto recompileObj;
	    }
	}

	/*
	 * #280.
	 * Literal sharing fix. This part of the fix is not required by 8.4
	 * because it eval-directs any literals, so just saving the argument
	 * locations per command in bytecode is enough, embedded 'eval'
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511

1512




1513




1514






1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
	 *     offset between saved starting line and actual one. Then modify
	 *     the users to adjust the locations they have by this offset.
	 *
	 * (3) Alternative 2: Do not fully recompile, adjust just the location
	 *     information.
	 */

	if (invoker == NULL) {
	    return codePtr;
	} else {
	    Tcl_HashEntry *hePtr =
		    Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);


	    ExtCmdLoc *eclPtr;
	    CmdFrame *ctxCopyPtr;
	    int redo;

	    if (!hePtr) {
		return codePtr;
	    }

	    eclPtr = Tcl_GetHashValue(hePtr);
	    redo = 0;
	    ctxCopyPtr = TclStackAlloc(interp, sizeof(CmdFrame));
	    *ctxCopyPtr = *invoker;

	    if (invoker->type == TCL_LOCATION_BC) {
		/*
		 * Note: Type BC => ctx.data.eval.path    is not used.
		 *		    ctx.data.tebc.codePtr used instead
		 */

		TclGetSrcInfoForPc(ctxCopyPtr);
		if (ctxCopyPtr->type == TCL_LOCATION_SOURCE) {
		    /*
		     * The reference made by 'TclGetSrcInfoForPc' is dead.

		     */

		    Tcl_DecrRefCount(ctxCopyPtr->data.eval.path);
		    ctxCopyPtr->data.eval.path = NULL;
		}
	    }

	    if (word < ctxCopyPtr->nline) {
		/*
		 * Note: We do not care if the line[word] is -1. This is a
		 * difference and requires a recompile (location changed from
		 * absolute to relative, literal is used fixed and through
		 * variable)
		 *
		 * Example:
		 * test info-32.0 using literal of info-24.8
		 *     (dict with ... vs           set body ...).
		 */

		redo = ((eclPtr->type == TCL_LOCATION_SOURCE)
			    && (eclPtr->start != ctxCopyPtr->line[word]))
			|| ((eclPtr->type == TCL_LOCATION_BC)
			    && (ctxCopyPtr->type == TCL_LOCATION_SOURCE));
	    }

	    TclStackFree(interp, ctxCopyPtr);

	    if (!redo) {




		return codePtr;




	    }






	}

    }

  recompileObj:
    iPtr->errorLine = 1;

    /*
     * TIP #280. Remember the invoker for a moment in the interpreter
     * structures so that the byte code compiler can pick it up when
     * initializing the compilation environment, i.e. the extended location
     * information.
     */

    iPtr->invokeCmdFramePtr = invoker;
    iPtr->invokeWord = word;
    TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
    iPtr->invokeCmdFramePtr = NULL;
    codePtr = (ByteCode *) objPtr->internalRep.twoPtrValue.ptr1;
    if (iPtr->varFramePtr->localCachePtr) {
	codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
	codePtr->localCachePtr->refCount++;
    }
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompEvalObj --
 *
 *	This procedure evaluates the script contained in a Tcl_Obj by first
 *	compiling it and then passing it to TclExecuteByteCode.
 *
 * Results:
 *	The return value is one of the return codes defined in tcl.h (such as
 *	TCL_OK), and interp->objResultPtr refers to a Tcl object that either
 *	contains the result of executing the code or an error message.
 *
 * Side effects:
 *	Almost certainly, depending on the ByteCode's instructions.
 *
 *----------------------------------------------------------------------
 */

int
TclCompEvalObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    register Interp *iPtr = (Interp *) interp;
    register ByteCode *codePtr;	/* Tcl Internal type of bytecode. */
    int result;

    /*
     * Check that the interpreter is ready to execute scripts. Note that we
     * manage the interp's runlevel here: it is a small white lie (maybe), but
     * saves a ++/-- pair at each invocation. Amazingly enough, the impact on
     * performance is noticeable.
     */

    iPtr->numLevels++;
    if (TclInterpReady(interp) == TCL_ERROR) {
	result = TCL_ERROR;
	goto done;
    }

    /* Compile objPtr to the byte code */
    codePtr = TclCompileObj(interp, objPtr, invoker, word);

    /*
     * Increment the code's ref count while it is being executed. If
     * afterwards no references to it remain, free the code.
     */

    codePtr->refCount++;
    result = TclExecuteByteCode(interp, codePtr);
    codePtr->refCount--;
    if (codePtr->refCount <= 0) {
	TclCleanupByteCode(codePtr);
    }

  done:
    iPtr->numLevels--;
    return result;
}

/*
 *----------------------------------------------------------------------
 *







|
<
<



>
|
<
|
|
<
<
|
<
<
<
<
|

|
|
|
|
|

|
|
|
|
>
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|

|
|

|
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>

>


|











|


<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







1464
1465
1466
1467
1468
1469
1470
1471


1472
1473
1474
1475
1476

1477
1478


1479




1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555






1556


1557























































1558
1559
1560
1561
1562
1563
1564
1565
	 *     offset between saved starting line and actual one. Then modify
	 *     the users to adjust the locations they have by this offset.
	 *
	 * (3) Alternative 2: Do not fully recompile, adjust just the location
	 *     information.
	 */

	if (invoker) {


	    Tcl_HashEntry *hePtr =
		    Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);

	    if (hePtr) {
		ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr);

		int redo = 0;
		CmdFrame *ctxPtr = TclStackAlloc(interp,sizeof(CmdFrame));







		*ctxPtr = *invoker;

		if (invoker->type == TCL_LOCATION_BC) {
		    /*
		     * Note: Type BC => ctx.data.eval.path    is not used.
		     *		    ctx.data.tebc.codePtr used instead
		     */

		    TclGetSrcInfoForPc(ctxPtr);
		    if (ctxPtr->type == TCL_LOCATION_SOURCE) {
			/*
			 * The reference made by 'TclGetSrcInfoForPc' is
			 * dead.
			 */

			Tcl_DecrRefCount(ctxPtr->data.eval.path);
			ctxPtr->data.eval.path = NULL;
		    }
		}

		if (word < ctxPtr->nline) {
		    /*
		     * Note: We do not care if the line[word] is -1. This
		     * is a difference and requires a recompile (location
		     * changed from absolute to relative, literal is used
		     * fixed and through variable)
		     *
		     * Example:
		     * test info-32.0 using literal of info-24.8
		     *     (dict with ... vs           set body ...).
		     */

		    redo = ((eclPtr->type == TCL_LOCATION_SOURCE)
			    && (eclPtr->start != ctxPtr->line[word]))
			|| ((eclPtr->type == TCL_LOCATION_BC)
				&& (ctxPtr->type == TCL_LOCATION_SOURCE));
		}

		TclStackFree(interp, ctxPtr);

		if (redo) {
		    goto recompileObj;
		}
	    }
	}

	/*
	 * Increment the code's ref count while it is being executed. If
	 * afterwards no references to it remain, free the code.
	 */

    runCompiledObj:
	codePtr->refCount++;
	result = TclExecuteByteCode(interp, codePtr);
	codePtr->refCount--;
	if (codePtr->refCount <= 0) {
	    TclCleanupByteCode(codePtr);
	}
	goto done;
    }

    recompileObj:
    iPtr->errorLine = 1;

    /*
     * TIP #280. Remember the invoker for a moment in the interpreter
     * structures so that the byte code compiler can pick it up when
     * initializing the compilation environment, i.e. the extended location
     * information.
     */

    iPtr->invokeCmdFramePtr = invoker;
    iPtr->invokeWord = word;
    tclByteCodeType.setFromAnyProc(interp, objPtr);
    iPtr->invokeCmdFramePtr = NULL;
    codePtr = (ByteCode *) objPtr->internalRep.twoPtrValue.ptr1;






    goto runCompiledObj;


























































    done:
    iPtr->numLevels--;
    return result;
}

/*
 *----------------------------------------------------------------------
 *
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
    register unsigned char *pc = codePtr->codeStart;
				/* The current program counter. */
    int instructionCount = 0;	/* Counter that is used to work out when to
				 * call Tcl_AsyncReady() */
    Tcl_Obj *expandNestList = NULL;
    int checkInterp = 0;	/* Indicates when a check of interp readyness
				 * is necessary. Set by CACHE_STACK_INFO() */
    int curEvalFlags = iPtr->evalFlags;

    /*
     * Transfer variables - needed only between opcodes, but not while
     * executing an instruction.
     */

    register int cleanup;







<







1746
1747
1748
1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759
    register unsigned char *pc = codePtr->codeStart;
				/* The current program counter. */
    int instructionCount = 0;	/* Counter that is used to work out when to
				 * call Tcl_AsyncReady() */
    Tcl_Obj *expandNestList = NULL;
    int checkInterp = 0;	/* Indicates when a check of interp readyness
				 * is necessary. Set by CACHE_STACK_INFO() */


    /*
     * Transfer variables - needed only between opcodes, but not while
     * executing an instruction.
     */

    register int cleanup;
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834

#ifdef TCL_COMPILE_DEBUG
    int traceInstructions = (tclTraceExec == 3);
    char cmdNameBuf[21];
#endif
    const char *curInstName = NULL;

    /*
     * Reset discard result flag - because it is applicable for this call only,
     * and should not affect all the nested invocations may return result.
     */
     iPtr->evalFlags &= ~TCL_EVAL_DISCARD_RESULT;

    /*
     * The execution uses a unified stack: first the catch stack, immediately
     * above it a CmdFrame, then the execution stack.
     *
     * Make sure the catch stack is large enough to hold the maximum number of
     * catch commands that could ever be executing at the same time (this will
     * be no more than the exception range array's depth). Make sure the







<
<
<
<
<
<







1774
1775
1776
1777
1778
1779
1780






1781
1782
1783
1784
1785
1786
1787

#ifdef TCL_COMPILE_DEBUG
    int traceInstructions = (tclTraceExec == 3);
    char cmdNameBuf[21];
#endif
    const char *curInstName = NULL;







    /*
     * The execution uses a unified stack: first the catch stack, immediately
     * above it a CmdFrame, then the execution stack.
     *
     * Make sure the catch stack is large enough to hold the maximum number of
     * catch commands that could ever be executing at the same time (this will
     * be no more than the exception range array's depth). Make sure the
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
	    Tcl_SetObjResult(interp, objResultPtr);
	    cleanup = 1;
	    goto processExceptionReturn;
	}

    case INST_DONE:
	if (tosPtr > initTosPtr) {

	    if ((curEvalFlags & TCL_EVAL_DISCARD_RESULT) && (result == TCL_OK)) {
		/* simulate pop & fast done (like it does continue in loop) */
		Tcl_Obj *objPtr;
		TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS);
		objPtr = POP_OBJECT();
		TclDecrRefCount(objPtr);
		goto abnormalReturn;
	    }
	    /*
	     * Set the interpreter's object result to point to the topmost
	     * object from the stack, and check for a possible [catch]. The
	     * stackTop's level and refCount will be handled by "processCatch"
	     * or "abnormalReturn".
	     */








<
<
<
<
<
<
<
<
<







2007
2008
2009
2010
2011
2012
2013









2014
2015
2016
2017
2018
2019
2020
	    Tcl_SetObjResult(interp, objResultPtr);
	    cleanup = 1;
	    goto processExceptionReturn;
	}

    case INST_DONE:
	if (tosPtr > initTosPtr) {









	    /*
	     * Set the interpreter's object result to point to the topmost
	     * object from the stack, and check for a possible [catch]. The
	     * stackTop's level and refCount will be handled by "processCatch"
	     * or "abnormalReturn".
	     */

2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
	}

    case INST_PUSH1:
    instPush1Peephole:
	PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
	TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
	pc += 2;
#if !defined(TCL_COMPILE_DEBUG)
	/*
	 * Runtime peephole optimisation: check if we are pushing again.
	 */

	if (*pc == INST_PUSH1) {
	    TCL_DTRACE_INST_NEXT();
	    goto instPush1Peephole;







|







2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
	}

    case INST_PUSH1:
    instPush1Peephole:
	PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
	TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
	pc += 2;
#if !TCL_COMPILE_DEBUG
	/*
	 * Runtime peephole optimisation: check if we are pushing again.
	 */

	if (*pc == INST_PUSH1) {
	    TCL_DTRACE_INST_NEXT();
	    goto instPush1Peephole;
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
	/*
	 * Runtime peephole optimisation: an INST_POP is scheduled at the end
	 * of most commands. If the next instruction is an INST_START_CMD,
	 * fall through to it.
	 */

	pc++;
#if !defined(TCL_COMPILE_DEBUG)
	if (*pc == INST_START_CMD) {
	    TCL_DTRACE_INST_NEXT();
	    goto instStartCmdPeephole;
	}
#endif
	NEXT_INST_F(0, 0, 0);
    }

    case INST_START_CMD:
#if !defined(TCL_COMPILE_DEBUG)
    instStartCmdPeephole:
#endif
	/*
	 * Remark that if the interpreter is marked for deletion its
	 * compileEpoch is modified, so that the epoch check also verifies
	 * that the interp is not deleted. If no outside call has been made
	 * since the last check, it is safe to omit the check.







|









|







2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
	/*
	 * Runtime peephole optimisation: an INST_POP is scheduled at the end
	 * of most commands. If the next instruction is an INST_START_CMD,
	 * fall through to it.
	 */

	pc++;
#if !TCL_COMPILE_DEBUG
	if (*pc == INST_START_CMD) {
	    TCL_DTRACE_INST_NEXT();
	    goto instStartCmdPeephole;
	}
#endif
	NEXT_INST_F(0, 0, 0);
    }

    case INST_START_CMD:
#if !TCL_COMPILE_DEBUG
    instStartCmdPeephole:
#endif
	/*
	 * Remark that if the interpreter is marked for deletion its
	 * compileEpoch is modified, so that the epoch check also verifies
	 * that the interp is not deleted. If no outside call has been made
	 * since the last check, it is safe to omit the check.
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290

	objResultPtr = OBJ_AT_DEPTH(opnd-1);
	bytes = TclGetStringFromObj(objResultPtr, &length);
	if (length + appendLen < 0) {
	    /* TODO: convert panic to error ? */
	    Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
	}
#if !defined(TCL_COMPILE_DEBUG)
	if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
	    TclFreeIntRep(objResultPtr);
	    objResultPtr->typePtr = NULL;
	    objResultPtr->bytes = ckrealloc(bytes, (length + appendLen + 1));
	    objResultPtr->length = length + appendLen;
	    p = TclGetString(objResultPtr) + length;
	    currPtr = &OBJ_AT_DEPTH(opnd - 2);
	} else {
#endif
	    p = (char *) ckalloc((unsigned) (length + appendLen + 1));
	    TclNewObj(objResultPtr);
	    objResultPtr->bytes = p;
	    objResultPtr->length = length + appendLen;
	    currPtr = &OBJ_AT_DEPTH(opnd - 1);
#if !defined(TCL_COMPILE_DEBUG)
	}
#endif

	/*
	 * Append the remaining characters.
	 */








|














|







2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234

	objResultPtr = OBJ_AT_DEPTH(opnd-1);
	bytes = TclGetStringFromObj(objResultPtr, &length);
	if (length + appendLen < 0) {
	    /* TODO: convert panic to error ? */
	    Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
	}
#if !TCL_COMPILE_DEBUG
	if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
	    TclFreeIntRep(objResultPtr);
	    objResultPtr->typePtr = NULL;
	    objResultPtr->bytes = ckrealloc(bytes, (length + appendLen + 1));
	    objResultPtr->length = length + appendLen;
	    p = TclGetString(objResultPtr) + length;
	    currPtr = &OBJ_AT_DEPTH(opnd - 2);
	} else {
#endif
	    p = (char *) ckalloc((unsigned) (length + appendLen + 1));
	    TclNewObj(objResultPtr);
	    objResultPtr->bytes = p;
	    objResultPtr->length = length + appendLen;
	    currPtr = &OBJ_AT_DEPTH(opnd - 1);
#if !TCL_COMPILE_DEBUG
	}
#endif

	/*
	 * Append the remaining characters.
	 */

4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960

4961
4962
4963
4964
4965




4966

4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
		     */

		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);
		}
#endif
		{
		    mp_int big1, big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);


		    if ((l1 > 0) ^ mp_isneg(&big2)) {
			/*
			 * Arguments are same sign; remainder is first operand.
			 */





			mp_clear(&big2);

			TRACE(("%s\n", O2S(valuePtr)));
			NEXT_INST_F(1, 1, 0);
		    }

		    /*
		     * Arguments are opposite sign; remainder is sum.
		     */

		    TclBNInitBignumFromLong(&big1, l1);
		    mp_add(&big2, &big1, &big2);
		    mp_clear(&big1);
		    objResultPtr = Tcl_NewBignumObj(&big2);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);
		}
	    }
#ifndef NO_WIDE_TYPE
	    if (type1 == TCL_NUMBER_WIDE) {
		Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1);

		if (type2 != TCL_NUMBER_BIG) {







|



>
|

|


>
>
>
>
|
>
|
|



|


<
<
|
<
|
|







4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924


4925

4926
4927
4928
4929
4930
4931
4932
4933
4934
		     */

		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);
		}
#endif
		{
		    mp_int big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((l1 > 0) ^ (big2.sign == MP_ZPOS)) {
			/*
			 * Arguments are opposite sign; remainder is sum.
			 */

			mp_int big1;

			TclBNInitBignumFromLong(&big1, l1);
			mp_add(&big2, &big1, &big2);
			mp_clear(&big1);
			objResultPtr = Tcl_NewBignumObj(&big2);
			TRACE(("%s\n", O2S(objResultPtr)));
			NEXT_INST_F(1, 2, 1);
		    }

		    /*
		     * Arguments are same sign; remainder is first operand.
		     */



		    mp_clear(&big2);

		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);
		}
	    }
#ifndef NO_WIDE_TYPE
	    if (type1 == TCL_NUMBER_WIDE) {
		Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1);

		if (type2 != TCL_NUMBER_BIG) {
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020




5021

5022
5023
5024

5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
		    }
		    wRemainder = w1 - w2*wQuotient;
		    objResultPtr = Tcl_NewWideIntObj(wRemainder);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);
		}
		{
		    mp_int big1, big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((w1 > ((Tcl_WideInt) 0)) ^ mp_isneg(&big2)) {
			/*
			 * Arguments are same sign; remainder is first operand.
			 */





			mp_clear(&big2);

			TRACE(("%s\n", O2S(valuePtr)));
			NEXT_INST_F(1, 1, 0);
		    }

		    /*
		     * Arguments are opposite sign; remainder is sum.
		     */

		    TclBNInitBignumFromWideInt(&big1, w1);
		    mp_add(&big2, &big1, &big2);
		    mp_clear(&big1);
		    objResultPtr = Tcl_NewBignumObj(&big2);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);

		}
	    }
#endif
	    {
		mp_int big1, big2, bigResult, bigRemainder;

		Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
		Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
		mp_init(&bigResult);
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		if (!mp_iszero(&bigRemainder)
			&& (mp_isneg(&bigRemainder) != mp_isneg(&big2))) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}







|
<



|

|


>
>
>
>
|
>
|
|

>

|


<
<
|
<
|
|
<












|







4951
4952
4953
4954
4955
4956
4957
4958

4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980


4981

4982
4983

4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
		    }
		    wRemainder = w1 - w2*wQuotient;
		    objResultPtr = Tcl_NewWideIntObj(wRemainder);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);
		}
		{
		    mp_int big2;

		    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

		    /* TODO: internals intrusion */
		    if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) {
			/*
			 * Arguments are opposite sign; remainder is sum.
			 */

			mp_int big1;

			TclBNInitBignumFromWideInt(&big1, w1);
			mp_add(&big2, &big1, &big2);
			mp_clear(&big1);
			objResultPtr = Tcl_NewBignumObj(&big2);
			TRACE(("%s\n", O2S(objResultPtr)));
			NEXT_INST_F(1, 2, 1);
		    }

		    /*
		     * Arguments are same sign; remainder is first operand.
		     */



		    mp_clear(&big2);

		    TRACE(("%s\n", O2S(valuePtr)));
		    NEXT_INST_F(1, 1, 0);

		}
	    }
#endif
	    {
		mp_int big1, big2, bigResult, bigRemainder;

		Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
		Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
		mp_init(&bigResult);
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		if (!mp_iszero(&bigRemainder)
			&& (bigRemainder.sign != big2.sign)) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}
5324
5325
5326
5327
5328
5329
5330
5331

5332
5333
5334
5335














5336
5337
5338
5339






























5340

5341
5342


5343


















5344

















5345
5346
5347

















5348















5349
5350
5351
5352
5353
5354
5355
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto checkForCatch;
	}

	if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) {
	    mp_int big1, big2, bigResult;


	    Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);















	    mp_init(&bigResult);

	    switch (*pc) {
	    case INST_BITAND:






























		mp_and(&big1, &big2, &bigResult);

		break;



	    case INST_BITOR:


















		mp_or(&big1, &big2, &bigResult);

















		break;

	    case INST_BITXOR:

















		mp_xor(&big1, &big2, &bigResult);















		break;
	    }

	    mp_clear(&big1);
	    mp_clear(&big2);
	    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
	    if (Tcl_IsShared(valuePtr)) {







|
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto checkForCatch;
	}

	if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) {
	    mp_int big1, big2, bigResult, *First, *Second;
	    int numPos;

	    Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

	    /*
	     * Count how many positive arguments we have. If only one of the
	     * arguments is negative, store it in 'Second'.
	     */

	    if (mp_cmp_d(&big1, 0) != MP_LT) {
		numPos = 1 + (mp_cmp_d(&big2, 0) != MP_LT);
		First = &big1;
		Second = &big2;
	    } else {
		First = &big2;
		Second = &big1;
		numPos = (mp_cmp_d(First, 0) != MP_LT);
	    }
	    mp_init(&bigResult);

	    switch (*pc) {
	    case INST_BITAND:
		switch (numPos) {
		case 2:
		    /*
		     * Both arguments positive, base case.
		     */

		    mp_and(First, Second, &bigResult);
		    break;
		case 1:
		    /*
		     * First is positive; second negative:
		     * P & N = P & ~~N = P&~(-N-1) = P & (P ^ (-N-1))
		     */

		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_xor(First, Second, &bigResult);
		    mp_and(First, &bigResult, &bigResult);
		    break;
		case 0:
		    /*
		     * Both arguments negative:
		     * a & b = ~ (~a | ~b) = -(-a-1|-b-1)-1
		     */

		    mp_neg(First, First);
		    mp_sub_d(First, 1, First);
		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_or(First, Second, &bigResult);
		    mp_neg(&bigResult, &bigResult);
		    mp_sub_d(&bigResult, 1, &bigResult);
		    break;
		}
		break;

	    case INST_BITOR:
		switch (numPos) {
		case 2:
		    /*
		     * Both arguments positive, base case.
		     */

		    mp_or(First, Second, &bigResult);
		    break;
		case 1:
		    /*
		     * First is positive; second negative:
		     * N|P = ~(~N&~P) = ~((-N-1)&~P) = -((-N-1)&((-N-1)^P))-1
		     */

		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_xor(First, Second, &bigResult);
		    mp_and(Second, &bigResult, &bigResult);
		    mp_neg(&bigResult, &bigResult);
		    mp_sub_d(&bigResult, 1, &bigResult);
		    break;
		case 0:
		    /*
		     * Both arguments negative:
		     * a | b = ~ (~a & ~b) = -(-a-1&-b-1)-1
		     */

		    mp_neg(First, First);
		    mp_sub_d(First, 1, First);
		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_and(First, Second, &bigResult);
		    mp_neg(&bigResult, &bigResult);
		    mp_sub_d(&bigResult, 1, &bigResult);
		    break;
		}
		break;

	    case INST_BITXOR:
		switch (numPos) {
		case 2:
		    /*
		     * Both arguments positive, base case.
		     */

		    mp_xor(First, Second, &bigResult);
		    break;
		case 1:
		    /*
		     * First is positive; second negative:
		     * P^N = ~(P^~N) = -(P^(-N-1))-1
		     */

		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_xor(First, Second, &bigResult);
		    mp_neg(&bigResult, &bigResult);
		    mp_sub_d(&bigResult, 1, &bigResult);
		    break;
		case 0:
		    /*
		     * Both arguments negative:
		     * a ^ b = (~a ^ ~b) = (-a-1^-b-1)
		     */

		    mp_neg(First, First);
		    mp_sub_d(First, 1, First);
		    mp_neg(Second, Second);
		    mp_sub_d(Second, 1, Second);
		    mp_xor(First, Second, &bigResult);
		    break;
		}
		break;
	    }

	    mp_clear(&big1);
	    mp_clear(&big2);
	    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
	    if (Tcl_IsShared(valuePtr)) {
6149
6150
6151
6152
6153
6154
6155

6156
6157
6158
6159
6160
6161
6162
6163
6164
		    mp_clear(&big1);
		    mp_clear(&big2);
		    mp_clear(&bigResult);
		    goto divideByZero;
		}
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);

		if (!mp_iszero(&bigRemainder)
			&& (mp_isneg(&bigRemainder) != mp_isneg(&big2))) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}







>

|







6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
		    mp_clear(&big1);
		    mp_clear(&big2);
		    mp_clear(&bigResult);
		    goto divideByZero;
		}
		mp_init(&bigRemainder);
		mp_div(&big1, &big2, &bigResult, &bigRemainder);
		/* TODO: internals intrusion */
		if (!mp_iszero(&bigRemainder)
			&& (bigRemainder.sign != big2.sign)) {
		    /*
		     * Convert to Tcl's integer division rules.
		     */

		    mp_sub_d(&bigResult, 1, &bigResult);
		    mp_add(&bigRemainder, &big2, &bigRemainder);
		}
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
				/* Points to closest loop or catch exception
				 * range enclosing the pc. Used by various
				 * instructions and processCatch to process
				 * break, continue, and errors. */
	Tcl_Obj *valuePtr;
	const char *bytes;
	int length;
#ifdef TCL_COMPILE_DEBUG
	int opnd;
#endif

	/*
	 * An external evaluation (INST_INVOKE or INST_EVAL) returned
	 * something different from TCL_OK, or else INST_BREAK or
	 * INST_CONTINUE were called.
	 */

    processExceptionReturn:
#ifdef TCL_COMPILE_DEBUG
	switch (*pc) {
	case INST_INVOKE_STK1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
	    break;
	case INST_INVOKE_STK4:
	    opnd = TclGetUInt4AtPtr(pc+1);







|










|







7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
				/* Points to closest loop or catch exception
				 * range enclosing the pc. Used by various
				 * instructions and processCatch to process
				 * break, continue, and errors. */
	Tcl_Obj *valuePtr;
	const char *bytes;
	int length;
#if TCL_COMPILE_DEBUG
	int opnd;
#endif

	/*
	 * An external evaluation (INST_INVOKE or INST_EVAL) returned
	 * something different from TCL_OK, or else INST_BREAK or
	 * INST_CONTINUE were called.
	 */

    processExceptionReturn:
#if TCL_COMPILE_DEBUG
	switch (*pc) {
	case INST_INVOKE_STK1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
	    break;
	case INST_INVOKE_STK4:
	    opnd = TclGetUInt4AtPtr(pc+1);
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->continueOffset);
		TRACE_APPEND(("%s, range at %d, new pc %d\n",
			StringForResultCode(result),
			rangePtr->codeOffset, rangePtr->continueOffset));
		NEXT_INST_F(0, 0, 0);
	    }
#ifdef TCL_COMPILE_DEBUG
	} else if (traceInstructions) {
	    if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
		Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
		TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
			result, O2S(objPtr)));
	    } else {
		Tcl_Obj *objPtr = Tcl_GetObjResult(interp);







|







7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->continueOffset);
		TRACE_APPEND(("%s, range at %d, new pc %d\n",
			StringForResultCode(result),
			rangePtr->codeOffset, rangePtr->continueOffset));
		NEXT_INST_F(0, 0, 0);
	    }
#if TCL_COMPILE_DEBUG
	} else if (traceInstructions) {
	    if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
		Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
		TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
			result, O2S(objPtr)));
	    } else {
		Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
	NEXT_INST_F(0, 0, 0);	/* Restart the execution loop at pc. */

	/*
	 * end of infinite loop dispatching on instructions.
	 */

	/*
	 * Done or abnormal return code. Restore the stack to state it had when
	 * starting to execute the ByteCode. Panic if the stack is below the
	 * initial level.
	 */

    abnormalReturn:
	TCL_DTRACE_INST_LAST();
	while (tosPtr > initTosPtr) {







|







7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
	NEXT_INST_F(0, 0, 0);	/* Restart the execution loop at pc. */

	/*
	 * end of infinite loop dispatching on instructions.
	 */

	/*
	 * Abnormal return code. Restore the stack to state it had when
	 * starting to execute the ByteCode. Panic if the stack is below the
	 * initial level.
	 */

    abnormalReturn:
	TCL_DTRACE_INST_LAST();
	while (tosPtr > initTosPtr) {

Changes to generic/tclFileName.c.

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
    }

    /*
     * Allocate a buffer large enough to hold the contents of all of the list
     * plus the argv pointers and the terminating NULL pointer.
     */

    *argvPtr = (const char **) ckalloc(
	    ((((*argcPtr) + 1) * sizeof(char *)) + size));

    /*
     * Position p after the last argv pointer and copy the contents of the
     * list in, piece by piece.
     */

    p = (char *) &(*argvPtr)[(*argcPtr) + 1];
    for (i = 0; i < *argcPtr; i++) {
	Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
	str = Tcl_GetStringFromObj(eltPtr, &len);
	memcpy(p, str, len + 1);
	p += len+1;
    }

    /*
     * Now set up the argv pointers.
     */








|











|







574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
    }

    /*
     * Allocate a buffer large enough to hold the contents of all of the list
     * plus the argv pointers and the terminating NULL pointer.
     */

    *argvPtr = (const char **) ckalloc((unsigned)
	    ((((*argcPtr) + 1) * sizeof(char *)) + size));

    /*
     * Position p after the last argv pointer and copy the contents of the
     * list in, piece by piece.
     */

    p = (char *) &(*argvPtr)[(*argcPtr) + 1];
    for (i = 0; i < *argcPtr; i++) {
	Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
	str = Tcl_GetStringFromObj(eltPtr, &len);
	memcpy(p, str, (size_t) len+1);
	p += len+1;
    }

    /*
     * Now set up the argv pointers.
     */

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

static Tcl_Obj *
SplitUnixPath(
    const char *path)		/* Pointer to string containing a path. */
{
    int length;
    const char *origPath = path, *elementStart;
    Tcl_Obj *result;

    /*
     * Deal with the root directory as a special case.
     */

    TclNewObj(result);
    if (*path == '/') {
	Tcl_Obj *rootElt;
	++path;
#if defined(__CYGWIN__) || defined(__QNX__)
	/*
	 * Check for "//" network path prefix
	 */







|





<







632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651

static Tcl_Obj *
SplitUnixPath(
    const char *path)		/* Pointer to string containing a path. */
{
    int length;
    const char *origPath = path, *elementStart;
    Tcl_Obj *result = Tcl_NewObj();

    /*
     * Deal with the root directory as a special case.
     */


    if (*path == '/') {
	Tcl_Obj *rootElt;
	++path;
#if defined(__CYGWIN__) || defined(__QNX__)
	/*
	 * Check for "//" network path prefix
	 */
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
SplitWinPath(
    const char *path)		/* Pointer to string containing a path. */
{
    int length;
    const char *p, *elementStart;
    Tcl_PathType type = TCL_PATH_ABSOLUTE;
    Tcl_DString buf;
    Tcl_Obj *result;
    Tcl_DStringInit(&buf);

    TclNewObj(result);
    p = ExtractWinRoot(path, &buf, 0, &type);

    /*
     * Terminate the root portion, if we matched something.
     */

    if (p != path) {







|


<







723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
SplitWinPath(
    const char *path)		/* Pointer to string containing a path. */
{
    int length;
    const char *p, *elementStart;
    Tcl_PathType type = TCL_PATH_ABSOLUTE;
    Tcl_DString buf;
    Tcl_Obj *result = Tcl_NewObj();
    Tcl_DStringInit(&buf);


    p = ExtractWinRoot(path, &buf, 0, &type);

    /*
     * Terminate the root portion, if we matched something.
     */

    if (p != path) {
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
char *
Tcl_JoinPath(
    int argc,
    const char *const *argv,
    Tcl_DString *resultPtr)	/* Pointer to previously initialized DString */
{
    int i, len;
    Tcl_Obj *listObj;
    Tcl_Obj *resultObj;
    const char *resultStr;

    /*
     * Build the list of paths.
     */

    TclNewObj(listObj);
    for (i = 0; i < argc; i++) {
	Tcl_ListObjAppendElement(NULL, listObj,
		Tcl_NewStringObj(argv[i], -1));
    }

    /*
     * Ask the objectified code to join the paths.







|







<







970
971
972
973
974
975
976
977
978
979
980
981
982
983
984

985
986
987
988
989
990
991
char *
Tcl_JoinPath(
    int argc,
    const char *const *argv,
    Tcl_DString *resultPtr)	/* Pointer to previously initialized DString */
{
    int i, len;
    Tcl_Obj *listObj = Tcl_NewObj();
    Tcl_Obj *resultObj;
    const char *resultStr;

    /*
     * Build the list of paths.
     */


    for (i = 0; i < argc; i++) {
	Tcl_ListObjAppendElement(NULL, listObj,
		Tcl_NewStringObj(argv[i], -1));
    }

    /*
     * Ask the objectified code to join the paths.
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

    /*
     * Convert forward slashes to backslashes in Windows paths because some
     * system interfaces don't accept forward slashes.
     */

    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
	char *p;
	for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) {
	    if (*p == '/') {
		*p = '\\';
	    }
	}
    }








|







1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079

    /*
     * Convert forward slashes to backslashes in Windows paths because some
     * system interfaces don't accept forward slashes.
     */

    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
	register char *p;
	for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) {
	    if (*p == '/') {
		*p = '\\';
	    }
	}
    }

1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_GlobObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, i, globFlags, length, join, dir, result;
    char *string;
    const char *separators;
    Tcl_Obj *typePtr, *resultPtr, *look;
    Tcl_Obj *pathOrDir = NULL;
    Tcl_DString prefix;
    static const char *options[] = {
	"-directory", "-join", "-nocomplain", "-path", "-tails",
	"-types", "--", NULL
    };
    enum globOptionsEnum {
	GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS,
	GLOB_TYPE, GLOB_LAST
    };
    enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
    Tcl_GlobTypeData *globTypes = NULL;
    (void)dummy;

    globFlags = 0;
    join = 0;
    dir = PATH_NONE;
    typePtr = NULL;
    for (i = 1; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,







>

















|





<







1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_GlobObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, i, globFlags, length, join, dir, result;
    char *string;
    const char *separators;
    Tcl_Obj *typePtr, *resultPtr, *look;
    Tcl_Obj *pathOrDir = NULL;
    Tcl_DString prefix;
    static const char *options[] = {
	"-directory", "-join", "-nocomplain", "-path", "-tails",
	"-types", "--", NULL
    };
    enum options {
	GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS,
	GLOB_TYPE, GLOB_LAST
    };
    enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
    Tcl_GlobTypeData *globTypes = NULL;


    globFlags = 0;
    join = 0;
    dir = PATH_NONE;
    typePtr = NULL;
    for (i = 1; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}

	switch ((enum globOptionsEnum) index) {
	case GLOB_NOCOMPLAIN:			/* -nocomplain */
	    globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
	    break;
	case GLOB_DIR:				/* -dir */
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-directory\"", -1));
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			dir == PATH_DIR
			    ? "\"-directory\" may only be used once"
			    : "\"-directory\" cannot be used with \"-path\"",
			-1));
		return TCL_ERROR;
	    }
	    dir = PATH_DIR;
	    globFlags |= TCL_GLOBMODE_DIR;
	    pathOrDir = objv[i+1];
	    i++;
	    break;







|











<
<
|
<







1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277


1278

1279
1280
1281
1282
1283
1284
1285
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}

	switch (index) {
	case GLOB_NOCOMPLAIN:			/* -nocomplain */
	    globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
	    break;
	case GLOB_DIR:				/* -dir */
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-directory\"", -1));
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(


			"\"-directory\" cannot be used with \"-path\"", -1));

		return TCL_ERROR;
	    }
	    dir = PATH_DIR;
	    globFlags |= TCL_GLOBMODE_DIR;
	    pathOrDir = objv[i+1];
	    i++;
	    break;
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-path\"", -1));
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			dir == PATH_GENERAL
			    ? "\"-path\" may only be used once"
			    : "\"-path\" cannot be used with \"-dictionary\"",
			-1));
		return TCL_ERROR;
	    }
	    dir = PATH_GENERAL;
	    pathOrDir = objv[i+1];
	    i++;
	    break;
	case GLOB_TYPE:				/* -types */







<
<
|
<







1293
1294
1295
1296
1297
1298
1299


1300

1301
1302
1303
1304
1305
1306
1307
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-path\"", -1));
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(


			"\"-path\" cannot be used with \"-directory\"", -1));

		return TCL_ERROR;
	    }
	    dir = PATH_GENERAL;
	    pathOrDir = objv[i+1];
	    i++;
	    break;
	case GLOB_TYPE:				/* -types */
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
    if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) {
	Tcl_AppendResult(interp,
		"\"-tails\" must be used with either "
		"\"-directory\" or \"-path\"", NULL);
	return TCL_ERROR;
    }

    separators = NULL;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;







|







1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
    if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) {
	Tcl_AppendResult(interp,
		"\"-tails\" must be used with either "
		"\"-directory\" or \"-path\"", NULL);
	return TCL_ERROR;
    }

    separators = NULL;		/* lint. */
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
	 * platform.
	 */

	Tcl_ListObjLength(interp, typePtr, &length);
	if (length <= 0) {
	    goto skipTypes;
	}
	globTypes = (Tcl_GlobTypeData *)
		TclStackAlloc(interp,sizeof(Tcl_GlobTypeData));
	globTypes->type = 0;
	globTypes->perm = 0;
	globTypes->macType = NULL;
	globTypes->macCreator = NULL;

	while (--length >= 0) {







|







1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
	 * platform.
	 */

	Tcl_ListObjLength(interp, typePtr, &length);
	if (length <= 0) {
	    goto skipTypes;
	}
	globTypes = (Tcl_GlobTypeData*)
		TclStackAlloc(interp,sizeof(Tcl_GlobTypeData));
	globTypes->type = 0;
	globTypes->perm = 0;
	globTypes->macType = NULL;
	globTypes->macCreator = NULL;

	while (--length >= 0) {
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
1685
1686
}

/*
 *----------------------------------------------------------------------
 *
 * TclGlob --
 *

 *	Sets the separator string based on the platform, performs tilde
 *	substitution, and calls DoGlob.
 *
 *	The interpreter's result, on entry to this function, must be a valid
 *	Tcl list (e.g. it could be empty), since we will lappend any new
 *	results to that list. If it is not a valid list, this function will
 *	fail to do anything very meaningful.
 *
 *	Note that if globFlags contains 'TCL_GLOBMODE_TAILS' then pathPrefix







>
|
|







1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
}

/*
 *----------------------------------------------------------------------
 *
 * TclGlob --
 *
 *	This procedure prepares arguments for the DoGlob call. It sets the
 *	separator string based on the platform, performs * tilde substitution,
 *	and calls DoGlob.
 *
 *	The interpreter's result, on entry to this function, must be a valid
 *	Tcl list (e.g. it could be empty), since we will lappend any new
 *	results to that list. If it is not a valid list, this function will
 *	fail to do anything very meaningful.
 *
 *	Note that if globFlags contains 'TCL_GLOBMODE_TAILS' then pathPrefix
1695
1696
1697
1698
1699
1700
1701

1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
 *
 * Side effects:
 *	The 'pattern' is written to.
 *
 *----------------------------------------------------------------------
 */


int
TclGlob(
    Tcl_Interp *interp,		/* Interpreter for returning error message or
				 * appending list of matching file names. */
    char *pattern,		/* Glob pattern to match. Must not refer to a
				 * static string. */
    Tcl_Obj *pathPrefix,	/* Path prefix to glob pattern, if non-null,
				 * which is considered literally. */
    int globFlags,		/* Stores or'ed combination of flags */
    Tcl_GlobTypeData *types)	/* Struct containing acceptable types. May be
				 * NULL. */
{
    const char *separators;
    const char *head;
    char *tail, *start;
    int result;
    Tcl_Obj *filenamesObj, *savedResultObj;

    separators = NULL;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;







>


















|







1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
 *
 * Side effects:
 *	The 'pattern' is written to.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
TclGlob(
    Tcl_Interp *interp,		/* Interpreter for returning error message or
				 * appending list of matching file names. */
    char *pattern,		/* Glob pattern to match. Must not refer to a
				 * static string. */
    Tcl_Obj *pathPrefix,	/* Path prefix to glob pattern, if non-null,
				 * which is considered literally. */
    int globFlags,		/* Stores or'ed combination of flags */
    Tcl_GlobTypeData *types)	/* Struct containing acceptable types. May be
				 * NULL. */
{
    const char *separators;
    const char *head;
    char *tail, *start;
    int result;
    Tcl_Obj *filenamesObj, *savedResultObj;

    separators = NULL;		/* lint. */
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
		&driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) {
	    pathPrefix = driveName;
	    tail += driveNameLen;
	}
    }

    /*
     * To process a [glob] invocation, this function may be called multiple
     * times. Each time, the previously discovered filenames are in the
     * interpreter result. We stash that away here so the result is free for
     * error messsages.
     */

    savedResultObj = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(savedResultObj);







|







1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
		&driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) {
	    pathPrefix = driveName;
	    tail += driveNameLen;
	}
    }

    /*
     * To process a [glob] invokation, this function may be called multiple
     * times. Each time, the previously discovered filenames are in the
     * interpreter result. We stash that away here so the result is free for
     * error messsages.
     */

    savedResultObj = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(savedResultObj);
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081

/*
 *----------------------------------------------------------------------
 *
 * SkipToChar --
 *
 *	This function traverses a glob pattern looking for the next unquoted
 *	occurrence of the specified character at the same braces nesting level.
 *
 * Results:
 *	Updates stringPtr to point to the matching character, or to the end of
 *	the string if nothing matched. The return value is 1 if a match was
 *	found at the top level, otherwise it is 0.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SkipToChar(
    char **stringPtr,		/* Pointer string to check. */
    int match)			/* Character to find. */
{
    int quoted, level;
    char *p;

    quoted = 0;
    level = 0;

    for (p = *stringPtr; *p != '\0'; p++) {
	if (quoted) {
	    quoted = 0;







|


















|







2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074

/*
 *----------------------------------------------------------------------
 *
 * SkipToChar --
 *
 *	This function traverses a glob pattern looking for the next unquoted
 *	occurance of the specified character at the same braces nesting level.
 *
 * Results:
 *	Updates stringPtr to point to the matching character, or to the end of
 *	the string if nothing matched. The return value is 1 if a match was
 *	found at the top level, otherwise it is 0.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SkipToChar(
    char **stringPtr,		/* Pointer string to check. */
    int match)			/* Character to find. */
{
    int quoted, level;
    register char *p;

    quoted = 0;
    level = 0;

    for (p = *stringPtr; *p != '\0'; p++) {
	if (quoted) {
	    quoted = 0;
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
		/*
		 * The current prefix must end in a separator.
		 */

		int len;
		const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);

		if ((len > 0) && (strchr(separators, joined[len-1]) == NULL)) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
	    Tcl_AppendToObj(joinedPtr, Tcl_DStringValue(&append),
		    Tcl_DStringLength(&append));
	}
	Tcl_IncrRefCount(joinedPtr);







|







2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
		/*
		 * The current prefix must end in a separator.
		 */

		int len;
		const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);

		if (strchr(separators, joined[len-1]) == NULL) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
	    Tcl_AppendToObj(joinedPtr, Tcl_DStringValue(&append),
		    Tcl_DStringLength(&append));
	}
	Tcl_IncrRefCount(joinedPtr);
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
	     * //machine/share/subdir *]' requires adding a separator here.
	     * This behaviour is not currently tested for in the test suite.
	     */

	    int len;
	    const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);

	    if ((len > 0) && (strchr(separators, joined[len-1]) == NULL)) {
		if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
	}
	Tcl_AppendToObj(joinedPtr, pattern, p-pattern);
    }







|







2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
	     * //machine/share/subdir *]' requires adding a separator here.
	     * This behaviour is not currently tested for in the test suite.
	     */

	    int len;
	    const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);

	    if (strchr(separators, joined[len-1]) == NULL) {
		if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
	}
	Tcl_AppendToObj(joinedPtr, pattern, p-pattern);
    }
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
 *
 *---------------------------------------------------------------------------
 */

Tcl_StatBuf *
Tcl_AllocStatBuf(void)
{
    return (Tcl_StatBuf *)ckalloc(sizeof(Tcl_StatBuf));
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|









2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
 *
 *---------------------------------------------------------------------------
 */

Tcl_StatBuf *
Tcl_AllocStatBuf(void)
{
    return (Tcl_StatBuf *) ckalloc(sizeof(Tcl_StatBuf));
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclGetDate.y.

962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
    }
}

int
TclClockOldscanObjCmd(
    ClientData clientData,	/* Unused */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of parameters */
    Tcl_Obj *CONST *objv)	/* Parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;







|







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
    }
}

int
TclClockOldscanObjCmd(
    ClientData clientData,	/* Unused */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *CONST *objv)	/* Parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;

Changes to generic/tclHash.c.

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

    /*
     * Search all of the entries in the appropriate bucket.
     */

    if (typePtr->compareKeysProc) {
	Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;

	if (typePtr->flags & TCL_HASH_KEY_DIRECT_COMPARE) {
	    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		    hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
		if (hash != PTR2UINT(hPtr->hash)) {
		    continue;
		}
#endif
		/* if keys pointers or values are equal */
		if ((key == hPtr->key.oneWordValue)
		    || compareKeysProc((VOID *) key, hPtr)
		) {
		    if (newPtr) {
			*newPtr = 0;
		    }
		    return hPtr;
		}
	    }
	} else {
	    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		    hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
		if (hash != PTR2UINT(hPtr->hash)) {
		    continue;
		}
#endif
		/* if needle pointer equals content pointer or values equal */
		if ((key == hPtr->key.string)
		    || compareKeysProc((VOID *) key, hPtr)
		) {
		    if (newPtr) {
			*newPtr = 0;
		    }
		    return hPtr;
		}
	    }
	}
    } else {
	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
	    if (hash != PTR2UINT(hPtr->hash)) {







<
<
|
|

|
|
|

<
<
|
<
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







313
314
315
316
317
318
319


320
321
322
323
324
325
326


327

328
329
330
331



















332
333
334
335
336
337
338

    /*
     * Search all of the entries in the appropriate bucket.
     */

    if (typePtr->compareKeysProc) {
	Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;


	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
	    if (hash != PTR2UINT(hPtr->hash)) {
		continue;
	    }
#endif


	    if (compareKeysProc((VOID *) key, hPtr)) {

		if (newPtr) {
		    *newPtr = 0;
		}
		return hPtr;



















	    }
	}
    } else {
	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
	    if (hash != PTR2UINT(hPtr->hash)) {
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
    unsigned int size, allocsize;

    allocsize = size = strlen(string) + 1;
    if (size < sizeof(hPtr->key)) {
	allocsize = sizeof(hPtr->key);
    }
    hPtr = (Tcl_HashEntry *) ckalloc(sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key));
    memset(hPtr, 0, sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key));
    memcpy(hPtr->key.string, string, size);
    hPtr->clientData = 0;
    return hPtr;
}

/*
 *----------------------------------------------------------------------







<







846
847
848
849
850
851
852

853
854
855
856
857
858
859
    unsigned int size, allocsize;

    allocsize = size = strlen(string) + 1;
    if (size < sizeof(hPtr->key)) {
	allocsize = sizeof(hPtr->key);
    }
    hPtr = (Tcl_HashEntry *) ckalloc(sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key));

    memcpy(hPtr->key.string, string, size);
    hPtr->clientData = 0;
    return hPtr;
}

/*
 *----------------------------------------------------------------------

Changes to generic/tclIO.c.

3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
    int srcLen,			/* Length of UTF-8 string in bytes. */
    Tcl_Encoding encoding)
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    char *nextNewLine = NULL;
    int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;
    char safe[BUFFER_PADDING];

    if (srcLen) {
        WillWrite(chanPtr);
    }

    /*
     * Write the terminated escape sequence even if srcLen is 0.
     */

    endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);

    if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
	    || (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
	nextNewLine = memchr(src, '\n', srcLen);
    }

    while (srcLen + saved + endEncoding > 0) {
	ChannelBuffer *bufPtr;
	char *dst;
	int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;

	if (nextNewLine) {
	    srcLimit = nextNewLine - src;
	}
	
	/* Get space to write into */







<


















|







3809
3810
3811
3812
3813
3814
3815

3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
    int srcLen,			/* Length of UTF-8 string in bytes. */
    Tcl_Encoding encoding)
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    char *nextNewLine = NULL;
    int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;


    if (srcLen) {
        WillWrite(chanPtr);
    }

    /*
     * Write the terminated escape sequence even if srcLen is 0.
     */

    endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);

    if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
	    || (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
	nextNewLine = memchr(src, '\n', srcLen);
    }

    while (srcLen + saved + endEncoding > 0) {
	ChannelBuffer *bufPtr;
	char *dst, safe[BUFFER_PADDING];
	int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;

	if (nextNewLine) {
	    srcLimit = nextNewLine - src;
	}
	
	/* Get space to write into */

Changes to generic/tclInt.decls.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclInt
scspec EXTERN

# Declare each of the functions in the unsupported internal Tcl
# interface.  These interfaces are allowed to changed between versions.
# Use at your own risk.  Note that the position of functions should not
# be changed between versions to avoid gratuitous incompatibilities.

# Replaced by Tcl_FSAccess in 8.4:







<







13
14
15
16
17
18
19

20
21
22
23
24
25
26
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclInt


# Declare each of the functions in the unsupported internal Tcl
# interface.  These interfaces are allowed to changed between versions.
# Use at your own risk.  Note that the position of functions should not
# be changed between versions to avoid gratuitous incompatibilities.

# Replaced by Tcl_FSAccess in 8.4:
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
}
declare 11 {
    void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 {
    void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr)
}
# Removed in 8.5:
#declare 13 {
#    int TclDoGlob(Tcl_Interp *interp, char *separators,
#	    Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types)
#}
declare 14 {
    int TclDumpMemoryInfo(ClientData clientData, int flags)
}
# Removed in 8.1:
#  declare 15 {
#      void TclExpandParseValue(ParseValue *pvPtr, int needed)
#  }
declare 16 {
    void TclExprFloatError(Tcl_Interp *interp, double value)
}
# Removed in 8.4:
#declare 17 {
#    int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
#}
#declare 18 {
#    int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv)
#}
#declare 19 {







|














|







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
}
declare 11 {
    void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 {
    void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr)
}
# Removed in 8.5
#declare 13 {
#    int TclDoGlob(Tcl_Interp *interp, char *separators,
#	    Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types)
#}
declare 14 {
    int TclDumpMemoryInfo(ClientData clientData, int flags)
}
# Removed in 8.1:
#  declare 15 {
#      void TclExpandParseValue(ParseValue *pvPtr, int needed)
#  }
declare 16 {
    void TclExprFloatError(Tcl_Interp *interp, double value)
}
# Removed in 8.4
#declare 17 {
#    int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
#}
#declare 18 {
#    int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv)
#}
#declare 19 {
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
declare 25 {
    void TclFreePackageInfo(Interp *iPtr)
}
# Removed in 8.1:
#  declare 26 {
#      char *TclGetCwd(Tcl_Interp *interp)
#  }
# Removed in 8.5:
#declare 27 {
#    int TclGetDate(char *p, unsigned long now, long zone,
#	    unsigned long *timePtr)
#}
declare 28 {
    Tcl_Channel TclpGetDefaultStdChannel(int type)
}







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
declare 25 {
    void TclFreePackageInfo(Interp *iPtr)
}
# Removed in 8.1:
#  declare 26 {
#      char *TclGetCwd(Tcl_Interp *interp)
#  }
# Removed in 8.5
#declare 27 {
#    int TclGetDate(char *p, unsigned long now, long zone,
#	    unsigned long *timePtr)
#}
declare 28 {
    Tcl_Channel TclpGetDefaultStdChannel(int type)
}
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
declare 31 {
    const char *TclGetExtension(const char *name)
}
declare 32 {
    int TclGetFrame(Tcl_Interp *interp, const char *str,
	    CallFrame **framePtrPtr)
}
# Removed in 8.5:
#declare 33 {
#    TclCmdProcType TclGetInterpProc(void)
#}
declare 34 {
    int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int endValue, int *indexPtr)
}







|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
declare 31 {
    const char *TclGetExtension(const char *name)
}
declare 32 {
    int TclGetFrame(Tcl_Interp *interp, const char *str,
	    CallFrame **framePtrPtr)
}
# Removed in Tcl 8.5
#declare 33 {
#    TclCmdProcType TclGetInterpProc(void)
#}
declare 34 {
    int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int endValue, int *indexPtr)
}
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
}
declare 41 {
    Tcl_Command TclGetOriginalCommand(Tcl_Command command)
}
declare 42 {
    char *TclpGetUserHome(const char *name, Tcl_DString *bufferPtr)
}
# Removed in 8.5a2:
#declare 43 {
#    int TclGlobalInvoke(Tcl_Interp *interp, int argc, const char **argv,
#	    int flags)
#}
declare 44 {
    int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr)
}
declare 45 {
    int TclHideUnsafeCommands(Tcl_Interp *interp)







|

|







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
}
declare 41 {
    Tcl_Command TclGetOriginalCommand(Tcl_Command command)
}
declare 42 {
    char *TclpGetUserHome(const char *name, Tcl_DString *bufferPtr)
}
# Removed in Tcl 8.5a2
#declare 43 {
#    int TclGlobalInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
#	    int flags)
#}
declare 44 {
    int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr)
}
declare 45 {
    int TclHideUnsafeCommands(Tcl_Interp *interp)
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
declare 50 {
    void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr,
	    Namespace *nsPtr)
}
declare 51 {
    int TclInterpInit(Tcl_Interp *interp)
}
# Removed in 8.5a2:
#declare 52 {
#    int TclInvoke(Tcl_Interp *interp, int argc, const char **argv,
#	    int flags)
#}
declare 53 {
    int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp,
	    int argc, CONST84 char **argv)
}
declare 54 {







|

|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
declare 50 {
    void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr,
	    Namespace *nsPtr)
}
declare 51 {
    int TclInterpInit(Tcl_Interp *interp)
}
# Removed in Tcl 8.5a2
#declare 52 {
#    int TclInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
#	    int flags)
#}
declare 53 {
    int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp,
	    int argc, CONST84 char **argv)
}
declare 54 {
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    int TclObjInterpProc(ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
}
declare 64 {
    int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
	    int flags)
}
# Removed in 8.5a2:
#declare 65 {
#    int TclObjInvokeGlobal(Tcl_Interp *interp, int objc,
#	    Tcl_Obj *const objv[], int flags)
#}
#declare 66 {
#    int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc)
#}







|







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
    int TclObjInterpProc(ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
}
declare 64 {
    int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
	    int flags)
}
# Removed in Tcl 8.5a2
#declare 65 {
#    int TclObjInvokeGlobal(Tcl_Interp *interp, int objc,
#	    Tcl_Obj *const objv[], int flags)
#}
#declare 66 {
#    int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc)
#}
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr,
	    Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description,
	    const char *procName)
}
declare 93 {
    void TclProcDeleteProc(ClientData clientData)
}
# Removed in 8.5:
#declare 94 {
#    int TclProcInterpProc(void *clientData, Tcl_Interp *interp,
#	    int argc, const char **argv)
#}
# Replaced by Tcl_FSStat in 8.4:
#declare 95 {
#    int TclpStat(const char *path, Tcl_StatBuf *buf)
#}
declare 96 {







|

|







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr,
	    Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description,
	    const char *procName)
}
declare 93 {
    void TclProcDeleteProc(ClientData clientData)
}
# Removed in Tcl 8.5:
#declare 94 {
#    int TclProcInterpProc(ClientData clientData, Tcl_Interp *interp,
#	    int argc, const char **argv)
#}
# Replaced by Tcl_FSStat in 8.4:
#declare 95 {
#    int TclpStat(const char *path, Tcl_StatBuf *buf)
#}
declare 96 {
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
#}
declare 138 {
    CONST84_RETURN char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
}
#declare 139 {
#    int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
#	    char *sym2, Tcl_PackageInitProc **proc1Ptr,
#	    Tcl_PackageInitProc **proc2Ptr, void **clientDataPtr)
#}
#declare 140 {
#    int TclLooksLikeInt(const char *bytes, int length)
#}
# This is used by TclX, but should otherwise be considered private
declare 141 {
    CONST84_RETURN char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
#}
declare 138 {
    CONST84_RETURN char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
}
#declare 139 {
#    int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
#	    char *sym2, Tcl_PackageInitProc **proc1Ptr,
#	    Tcl_PackageInitProc **proc2Ptr, ClientData *clientDataPtr)
#}
#declare 140 {
#    int TclLooksLikeInt(const char *bytes, int length)
#}
# This is used by TclX, but should otherwise be considered private
declare 141 {
    CONST84_RETURN char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
}
declare 153 {
    Tcl_Obj *TclGetLibraryPath(void)
}

# moved to tclTest.c (static) in 8.3.2/8.4a2
#declare 154 {
#    int TclTestChannelCmd(void *clientData,
#    Tcl_Interp *interp, int argc, char **argv)
#}
#declare 155 {
#    int TclTestChannelEventCmd(void *clientData,
#	     Tcl_Interp *interp, int argc, char **argv)
#}

declare 156 {
    void TclRegError(Tcl_Interp *interp, const char *msg,
	    int status)
}







|



|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
}
declare 153 {
    Tcl_Obj *TclGetLibraryPath(void)
}

# moved to tclTest.c (static) in 8.3.2/8.4a2
#declare 154 {
#    int TclTestChannelCmd(ClientData clientData,
#    Tcl_Interp *interp, int argc, char **argv)
#}
#declare 155 {
#    int TclTestChannelEventCmd(ClientData clientData,
#	     Tcl_Interp *interp, int argc, char **argv)
#}

declare 156 {
    void TclRegError(Tcl_Interp *interp, const char *msg,
	    int status)
}
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
    void TclDbDumpActiveObjects(FILE *outFile)
}

declare 249 {
    char *TclDoubleDigits(double dv, int ndigits, int flags,
			  int *decpt, int *signum, char **endPtr)
}

# Allow extensions for optimization
declare 251 {
    int TclRegisterLiteral(void *envPtr,
	    char *bytes, int length, int flags)
}

declare 257 {
    void TclStaticPackage(Tcl_Interp *interp, const char *pkgName,
	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
}

declare 261 {
    void TclUnusedStubEntry(void)
}

##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







940
941
942
943
944
945
946















947
948
949
950
951
952
953
    void TclDbDumpActiveObjects(FILE *outFile)
}

declare 249 {
    char *TclDoubleDigits(double dv, int ndigits, int flags,
			  int *decpt, int *signum, char **endPtr)
}
















##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat

Changes to generic/tclInt.h.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#endif
#ifdef NO_STRING_H
#include "../compat/string.h"
#else
#include <string.h>
#endif
#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
     || defined(__cplusplus) || defined(_MSC_VER) || defined(__ICC)
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif

/*
 * Ensure WORDS_BIGENDIAN is defined correctly:







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#endif
#ifdef NO_STRING_H
#include "../compat/string.h"
#else
#include <string.h>
#endif
#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
     || defined(__cplusplus) || defined(_MSC_VER)
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif

/*
 * Ensure WORDS_BIGENDIAN is defined correctly:
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
 * EvalFlag bits for Interp structures:
 *
 * TCL_ALLOW_EXCEPTIONS	1 means it's OK for the script to terminate with a
 *			code other than TCL_OK or TCL_ERROR; 0 means codes
 *			other than these should be turned into errors.
 */

#define TCL_ALLOW_EXCEPTIONS		0x04
#define TCL_EVAL_FILE			0x02
#define TCL_EVAL_CTX			0x08
#define TCL_EVAL_DISCARD_RESULT		0x40

/*
 * Flag bits for Interp structures:
 *
 * DELETED:		Non-zero means the interpreter has been deleted:
 *			don't process any more commands for it, and destroy
 *			the structure as soon as all nested invocations of







|
|
|
<







1972
1973
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
 * EvalFlag bits for Interp structures:
 *
 * TCL_ALLOW_EXCEPTIONS	1 means it's OK for the script to terminate with a
 *			code other than TCL_OK or TCL_ERROR; 0 means codes
 *			other than these should be turned into errors.
 */

#define TCL_ALLOW_EXCEPTIONS	4
#define TCL_EVAL_FILE		2
#define TCL_EVAL_CTX		8


/*
 * Flag bits for Interp structures:
 *
 * DELETED:		Non-zero means the interpreter has been deleted:
 *			don't process any more commands for it, and destroy
 *			the structure as soon as all nested invocations of
2604
2605
2606
2607
2608
2609
2610

2611
2612
2613
2614
2615
2616
2617
MODULE_SCOPE void	TclInitIOSubsystem(void);
MODULE_SCOPE void	TclInitLimitSupport(Tcl_Interp *interp);
MODULE_SCOPE void	TclInitNamespaceSubsystem(void);
MODULE_SCOPE void	TclInitNotifier(void);
MODULE_SCOPE void	TclInitObjSubsystem(void);
MODULE_SCOPE void	TclInitSubsystems(void);
MODULE_SCOPE int	TclInterpReady(Tcl_Interp *interp);

MODULE_SCOPE int	TclIsBareword(char byte);
MODULE_SCOPE int	TclJoinThread(Tcl_ThreadId id, int *result);
MODULE_SCOPE void	TclLimitRemoveAllHandlers(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclLindexList(Tcl_Interp *interp,
			    Tcl_Obj *listPtr, Tcl_Obj *argPtr);
MODULE_SCOPE Tcl_Obj *	TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[]);







>







2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
MODULE_SCOPE void	TclInitIOSubsystem(void);
MODULE_SCOPE void	TclInitLimitSupport(Tcl_Interp *interp);
MODULE_SCOPE void	TclInitNamespaceSubsystem(void);
MODULE_SCOPE void	TclInitNotifier(void);
MODULE_SCOPE void	TclInitObjSubsystem(void);
MODULE_SCOPE void	TclInitSubsystems(void);
MODULE_SCOPE int	TclInterpReady(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsSpaceProc(char byte);
MODULE_SCOPE int	TclIsBareword(char byte);
MODULE_SCOPE int	TclJoinThread(Tcl_ThreadId id, int *result);
MODULE_SCOPE void	TclLimitRemoveAllHandlers(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclLindexList(Tcl_Interp *interp,
			    Tcl_Obj *listPtr, Tcl_Obj *argPtr);
MODULE_SCOPE Tcl_Obj *	TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[]);
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652


2653
2654
2655
2656
2657
2658
2659
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
			    const EnsembleImplMap map[]);
MODULE_SCOPE int	TclMaxListLength(CONST char *bytes, int numBytes,
			    CONST char **endPtr);
MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE int	TclNokia770Doubles(void);
MODULE_SCOPE void	TclNsDecrRefCount(Namespace *nsPtr);
MODULE_SCOPE int	TclNamespaceDeleted(Namespace *nsPtr);
MODULE_SCOPE void	TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const char *operation,
			    const char *reason, int index);
MODULE_SCOPE int	TclObjInvokeNamespace(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[],
			    Tcl_Namespace *nsPtr, int flags);
MODULE_SCOPE int	TclObjUnsetVar2(Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags);
MODULE_SCOPE int	TclParseBackslash(const char *src,
			    int numBytes, int *readPtr, char *dst);


MODULE_SCOPE int	TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const char *expected, const char *bytes,
			    int numBytes, const char **endPtrPtr, int flags);
MODULE_SCOPE void	TclParseInit(Tcl_Interp *interp, const char *string,
			    int numBytes, Tcl_Parse *parsePtr);
MODULE_SCOPE int	TclParseAllWhiteSpace(const char *src, int numBytes);
MODULE_SCOPE int	TclProcessReturn(Tcl_Interp *interp,







|
<
<










>
>







2633
2634
2635
2636
2637
2638
2639
2640


2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
			    const EnsembleImplMap map[]);
MODULE_SCOPE int	TclMaxListLength(CONST char *bytes, int numBytes,
			    CONST char **endPtr);
MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE int	TclNokia770Doubles();


MODULE_SCOPE void	TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const char *operation,
			    const char *reason, int index);
MODULE_SCOPE int	TclObjInvokeNamespace(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[],
			    Tcl_Namespace *nsPtr, int flags);
MODULE_SCOPE int	TclObjUnsetVar2(Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags);
MODULE_SCOPE int	TclParseBackslash(const char *src,
			    int numBytes, int *readPtr, char *dst);
MODULE_SCOPE int	TclParseHex(const char *src, int numBytes,
			    Tcl_UniChar *resultPtr);
MODULE_SCOPE int	TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const char *expected, const char *bytes,
			    int numBytes, const char **endPtrPtr, int flags);
MODULE_SCOPE void	TclParseInit(Tcl_Interp *interp, const char *string,
			    int numBytes, Tcl_Parse *parsePtr);
MODULE_SCOPE int	TclParseAllWhiteSpace(const char *src, int numBytes);
MODULE_SCOPE int	TclProcessReturn(Tcl_Interp *interp,
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
MODULE_SCOPE int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int codeSize, Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
#endif
MODULE_SCOPE void	TclInitThreadStorage(void);
MODULE_SCOPE void	TclpFinalizeThreadDataThread(void);
MODULE_SCOPE void	TclFinalizeThreadStorage(void);

/* TclWideMUInt -- wide integer used for measurement calculations: */
#if (!defined(_WIN32) || !defined(_MSC_VER) || (_MSC_VER >= 1400))
#   define TclWideMUInt Tcl_WideUInt
#else
/* older MSVS may not allow conversions between unsigned __int64 and double) */
#   define TclWideMUInt Tcl_WideInt
#endif
#ifdef TCL_WIDE_CLICKS
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClicksToNanoseconds(Tcl_WideInt clicks);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#else
#   ifdef _WIN32
#	define TCL_WIDE_CLICKS 1
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#	define		TclpWideClicksToNanoseconds(clicks) \
				((double)(clicks) * TclpWideClickInMicrosec() * 1000)
#   endif
#endif
MODULE_SCOPE Tcl_WideInt TclpGetMicroseconds(void);

MODULE_SCOPE Tcl_Obj *	TclDisassembleByteCodeObj(Tcl_Obj *objPtr);
MODULE_SCOPE int TclUtfCasecmp(CONST char *cs, CONST char *ct);

/*
 * Many parsing tasks need a common definition of whitespace.
 * Use this routine and macro to achieve that and place
 * optimization (fragile on changes) in one place.
 */

MODULE_SCOPE int	TclIsSpaceProc(char byte);
#	define TclIsSpaceProcM(byte) \
		(((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd(ClientData clientData,







<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<
<

<
<



<
<
<
<
<
<
<
<
<
<







2766
2767
2768
2769
2770
2771
2772








2773
2774
2775









2776


2777
2778
2779










2780
2781
2782
2783
2784
2785
2786
MODULE_SCOPE int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int codeSize, Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
#endif
MODULE_SCOPE void	TclInitThreadStorage(void);
MODULE_SCOPE void	TclpFinalizeThreadDataThread(void);
MODULE_SCOPE void	TclFinalizeThreadStorage(void);








#ifdef TCL_WIDE_CLICKS
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClicksToNanoseconds(Tcl_WideInt clicks);









#endif


MODULE_SCOPE Tcl_Obj *	TclDisassembleByteCodeObj(Tcl_Obj *objPtr);
MODULE_SCOPE int TclUtfCasecmp(CONST char *cs, CONST char *ct);











/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd(ClientData clientData,
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TellObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeRateObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TraceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnloadObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnsetObjCmd(ClientData clientData,







<
<
<







3012
3013
3014
3015
3016
3017
3018



3019
3020
3021
3022
3023
3024
3025
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TellObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);



MODULE_SCOPE int	Tcl_TraceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnloadObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnsetObjCmd(ClientData clientData,
3298
3299
3300
3301
3302
3303
3304



3305
3306
3307



3308
3309
3310



3311
3312
3313



3314
3315
3316



3317
3318
3319



3320
3321
3322
3323
3324
3325
3326
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclDivOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileDivOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileLessOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileLeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileGreaterOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileGeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileEqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);



MODULE_SCOPE int	TclCompileStreqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

/*
 * Functions defined in generic/tclVar.c and currenttly exported only for use
 * by the bytecode compiler and engine. Some of these could later be placed in







>
>
>



>
>
>



>
>
>



>
>
>



>
>
>



>
>
>







3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclDivOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileDivOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclLessOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileLessOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclLeqOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileLeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclGreaterOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileGreaterOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclGeqOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileGeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclEqOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileEqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclStreqOpCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileStreqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

/*
 * Functions defined in generic/tclVar.c and currenttly exported only for use
 * by the bytecode compiler and engine. Some of these could later be placed in
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
 * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	(((UCHAR(*(str))) < 0x80) ?		\
	    ((*(chPtr) = UCHAR(*(str))), 1)	\
	    : Tcl_UtfToUniChar(str, chPtr))

#define TclUtfPrev(src, start) \
	(((src) < (start)+2) ? (start) : \
	(UCHAR(*((src) - 1))) < 0x80 ? (src)-1 : \
	Tcl_UtfPrev(src, start))

#define TclUtfNext(src)	\
	(((UCHAR(*(src))) < 0x80) ? src + 1 : Tcl_UtfNext(src))

/*
 *----------------------------------------------------------------
 * Macro that encapsulates the logic that determines when it is safe to
 * interpret a string as a byte array directly. In summary, the object must be
 * a byte array and must not have a string representation (as the operations
 * that it is used in are defined on strings, not byte arrays). Theoretically
 * it is possible to also be efficient in the case where the object's bytes







|
|


<
<
<
<
<
<
<
<







3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677








3678
3679
3680
3681
3682
3683
3684
 * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0xC0) ?		\
	    ((*(chPtr) = (unsigned char) *(str)), 1)	\
	    : Tcl_UtfToUniChar(str, chPtr))









/*
 *----------------------------------------------------------------
 * Macro that encapsulates the logic that determines when it is safe to
 * interpret a string as a byte array directly. In summary, the object must be
 * a byte array and must not have a string representation (as the operations
 * that it is used in are defined on strings, not byte arrays). Theoretically
 * it is possible to also be efficient in the case where the object's bytes

Changes to generic/tclIntDecls.h.

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
/* Slot 248 is reserved */
#ifndef TclDoubleDigits_TCL_DECLARED
#define TclDoubleDigits_TCL_DECLARED
/* 249 */
EXTERN char *		TclDoubleDigits(double dv, int ndigits, int flags,
				int *decpt, int *signum, char **endPtr);
#endif
/* Slot 250 is reserved */
#ifndef TclRegisterLiteral_TCL_DECLARED
#define TclRegisterLiteral_TCL_DECLARED
/* 251 */
EXTERN int		TclRegisterLiteral(VOID *envPtr, char *bytes,
				int length, int flags);
#endif
/* Slot 252 is reserved */
/* Slot 253 is reserved */
/* Slot 254 is reserved */
/* Slot 255 is reserved */
/* Slot 256 is reserved */
#ifndef TclStaticPackage_TCL_DECLARED
#define TclStaticPackage_TCL_DECLARED
/* 257 */
EXTERN void		TclStaticPackage(Tcl_Interp *interp,
				CONST char *pkgName,
				Tcl_PackageInitProc *initProc,
				Tcl_PackageInitProc *safeInitProc);
#endif
/* Slot 258 is reserved */
/* Slot 259 is reserved */
/* Slot 260 is reserved */
#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 261 */
EXTERN void		TclUnusedStubEntry(void);
#endif

typedef struct TclIntStubs {
    int magic;
    struct TclIntStubHooks *hooks;

    VOID *reserved0;
    VOID *reserved1;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1052
1053
1054
1055
1056
1057
1058




























1059
1060
1061
1062
1063
1064
1065
/* Slot 248 is reserved */
#ifndef TclDoubleDigits_TCL_DECLARED
#define TclDoubleDigits_TCL_DECLARED
/* 249 */
EXTERN char *		TclDoubleDigits(double dv, int ndigits, int flags,
				int *decpt, int *signum, char **endPtr);
#endif





























typedef struct TclIntStubs {
    int magic;
    struct TclIntStubHooks *hooks;

    VOID *reserved0;
    VOID *reserved1;
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
    void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
    VOID *reserved244;
    VOID *reserved245;
    VOID *reserved246;
    VOID *reserved247;
    VOID *reserved248;
    char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
    VOID *reserved250;
    int (*tclRegisterLiteral) (VOID *envPtr, char *bytes, int length, int flags); /* 251 */
    VOID *reserved252;
    VOID *reserved253;
    VOID *reserved254;
    VOID *reserved255;
    VOID *reserved256;
    void (*tclStaticPackage) (Tcl_Interp *interp, CONST char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 257 */
    VOID *reserved258;
    VOID *reserved259;
    VOID *reserved260;
    void (*tclUnusedStubEntry) (void); /* 261 */
} TclIntStubs;

extern TclIntStubs *tclIntStubsPtr;

#ifdef __cplusplus
}
#endif







<
<
<
<
<
<
<
<
<
<
<
<







1307
1308
1309
1310
1311
1312
1313












1314
1315
1316
1317
1318
1319
1320
    void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
    VOID *reserved244;
    VOID *reserved245;
    VOID *reserved246;
    VOID *reserved247;
    VOID *reserved248;
    char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */












} TclIntStubs;

extern TclIntStubs *tclIntStubsPtr;

#ifdef __cplusplus
}
#endif
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
/* Slot 246 is reserved */
/* Slot 247 is reserved */
/* Slot 248 is reserved */
#ifndef TclDoubleDigits
#define TclDoubleDigits \
	(tclIntStubsPtr->tclDoubleDigits) /* 249 */
#endif
/* Slot 250 is reserved */
#ifndef TclRegisterLiteral
#define TclRegisterLiteral \
	(tclIntStubsPtr->tclRegisterLiteral) /* 251 */
#endif
/* Slot 252 is reserved */
/* Slot 253 is reserved */
/* Slot 254 is reserved */
/* Slot 255 is reserved */
/* Slot 256 is reserved */
#ifndef TclStaticPackage
#define TclStaticPackage \
	(tclIntStubsPtr->tclStaticPackage) /* 257 */
#endif
/* Slot 258 is reserved */
/* Slot 259 is reserved */
/* Slot 260 is reserved */
#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclIntStubsPtr->tclUnusedStubEntry) /* 261 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#if !defined(_WIN64)
/* See bug 510001: TclSockMinimumBuffers needs plat imp */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2036
2037
2038
2039
2040
2041
2042





















2043
2044
2045
2046
2047
2048
2049
/* Slot 246 is reserved */
/* Slot 247 is reserved */
/* Slot 248 is reserved */
#ifndef TclDoubleDigits
#define TclDoubleDigits \
	(tclIntStubsPtr->tclDoubleDigits) /* 249 */
#endif






















#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#if !defined(_WIN64)
/* See bug 510001: TclSockMinimumBuffers needs plat imp */

Changes to generic/tclInterp.c.

919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
	switch ((enum LimitTypes) limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return SlaveCommandLimitCmd(interp, slaveInterp, 4, objc,objv);
	case LIMIT_TYPE_TIME:
	    return SlaveTimeLimitCmd(interp, slaveInterp, 4, objc, objv);
	}
    }
    break;
    case OPT_MARKTRUSTED: {
	Tcl_Interp *slaveInterp;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "path");
	    return TCL_ERROR;
	}







<







919
920
921
922
923
924
925

926
927
928
929
930
931
932
	switch ((enum LimitTypes) limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return SlaveCommandLimitCmd(interp, slaveInterp, 4, objc,objv);
	case LIMIT_TYPE_TIME:
	    return SlaveTimeLimitCmd(interp, slaveInterp, 4, objc, objv);
	}
    }

    case OPT_MARKTRUSTED: {
	Tcl_Interp *slaveInterp;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "path");
	    return TCL_ERROR;
	}
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
	switch ((enum LimitTypes) limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return SlaveCommandLimitCmd(interp, slaveInterp, 3, objc,objv);
	case LIMIT_TYPE_TIME:
	    return SlaveTimeLimitCmd(interp, slaveInterp, 3, objc, objv);
	}
    }
    break;
    case OPT_MARKTRUSTED:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	return SlaveMarkTrusted(interp, slaveInterp);
    case OPT_RECLIMIT:







<







2429
2430
2431
2432
2433
2434
2435

2436
2437
2438
2439
2440
2441
2442
	switch ((enum LimitTypes) limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return SlaveCommandLimitCmd(interp, slaveInterp, 3, objc,objv);
	case LIMIT_TYPE_TIME:
	    return SlaveTimeLimitCmd(interp, slaveInterp, 3, objc, objv);
	}
    }

    case OPT_MARKTRUSTED:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	return SlaveMarkTrusted(interp, slaveInterp);
    case OPT_RECLIMIT:

Changes to generic/tclLink.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * For each linked variable there is a data structure of the following type,
 * which describes the link and is the clientData for the trace set on the Tcl
 * variable.
 */

typedef struct Link {
    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
    Namespace *nsPtr;		/* Namespace containing Tcl variable */
    Tcl_Obj *varName;		/* Name of variable (must be global). This is
				 * needed during trace callbacks, since the
				 * actual variable may be aliased at that time
				 * via upvar. */
    char *addr;			/* Location of C variable. */
    int type;			/* Type of link (TCL_LINK_INT, etc.). */
    union {







<







19
20
21
22
23
24
25

26
27
28
29
30
31
32
 * For each linked variable there is a data structure of the following type,
 * which describes the link and is the clientData for the trace set on the Tcl
 * variable.
 */

typedef struct Link {
    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */

    Tcl_Obj *varName;		/* Name of variable (must be global). This is
				 * needed during trace callbacks, since the
				 * actual variable may be aliased at that time
				 * via upvar. */
    char *addr;			/* Location of C variable. */
    int type;			/* Type of link (TCL_LINK_INT, etc.). */
    union {
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
    char *addr,			/* Address of a C variable to be linked to
				 * varName. */
    int type)			/* Type of C variable: TCL_LINK_INT, etc. Also
				 * may have TCL_LINK_READ_ONLY OR'ed in. */
{
    Tcl_Obj *objPtr;
    Link *linkPtr;
    Namespace *dummy;
    const char *name;
    int code;

    linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
	    LinkTraceProc, (ClientData) NULL);
    if (linkPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"variable '%s' is already linked", varName));
	return TCL_ERROR;
    }

    linkPtr = (Link *) ckalloc(sizeof(Link));
    linkPtr->interp = interp;
    linkPtr->nsPtr = NULL;
    linkPtr->varName = Tcl_NewStringObj(varName, -1);
    Tcl_IncrRefCount(linkPtr->varName);
    linkPtr->addr = addr;
    linkPtr->type = type & ~TCL_LINK_READ_ONLY;
    if (type & TCL_LINK_READ_ONLY) {
	linkPtr->flags = LINK_READ_ONLY;
    } else {
	linkPtr->flags = 0;
    }
    objPtr = ObjValue(linkPtr);
    if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
	    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
	Tcl_DecrRefCount(linkPtr->varName);
	ckfree((char *) linkPtr);
	return TCL_ERROR;
    }

    TclGetNamespaceForQualName(interp, varName, NULL, TCL_GLOBAL_ONLY,
	    &(linkPtr->nsPtr), &dummy, &dummy, &name);
    linkPtr->nsPtr->refCount++;

    code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS
	    |TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc,
	    (ClientData) linkPtr);
    if (code != TCL_OK) {
	Tcl_DecrRefCount(linkPtr->varName);
	TclNsDecrRefCount(linkPtr->nsPtr);
	ckfree((char *) linkPtr);
    }
    return code;
}

/*
 *----------------------------------------------------------------------







<
<












<
















<
<
<
<
<





<







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
140
141
142
143
144





145
146
147
148
149

150
151
152
153
154
155
156
    char *addr,			/* Address of a C variable to be linked to
				 * varName. */
    int type)			/* Type of C variable: TCL_LINK_INT, etc. Also
				 * may have TCL_LINK_READ_ONLY OR'ed in. */
{
    Tcl_Obj *objPtr;
    Link *linkPtr;


    int code;

    linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
	    LinkTraceProc, (ClientData) NULL);
    if (linkPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"variable '%s' is already linked", varName));
	return TCL_ERROR;
    }

    linkPtr = (Link *) ckalloc(sizeof(Link));
    linkPtr->interp = interp;

    linkPtr->varName = Tcl_NewStringObj(varName, -1);
    Tcl_IncrRefCount(linkPtr->varName);
    linkPtr->addr = addr;
    linkPtr->type = type & ~TCL_LINK_READ_ONLY;
    if (type & TCL_LINK_READ_ONLY) {
	linkPtr->flags = LINK_READ_ONLY;
    } else {
	linkPtr->flags = 0;
    }
    objPtr = ObjValue(linkPtr);
    if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
	    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
	Tcl_DecrRefCount(linkPtr->varName);
	ckfree((char *) linkPtr);
	return TCL_ERROR;
    }





    code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS
	    |TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc,
	    (ClientData) linkPtr);
    if (code != TCL_OK) {
	Tcl_DecrRefCount(linkPtr->varName);

	ckfree((char *) linkPtr);
    }
    return code;
}

/*
 *----------------------------------------------------------------------
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
    if (linkPtr == NULL) {
	return;
    }
    Tcl_UntraceVar(interp, varName,
	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    LinkTraceProc, (ClientData) linkPtr);
    Tcl_DecrRefCount(linkPtr->varName);
    if (linkPtr->nsPtr) {
	TclNsDecrRefCount(linkPtr->nsPtr);
    }
    ckfree((char *) linkPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UpdateLinkedVar --







<
<
<







182
183
184
185
186
187
188



189
190
191
192
193
194
195
    if (linkPtr == NULL) {
	return;
    }
    Tcl_UntraceVar(interp, varName,
	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    LinkTraceProc, (ClientData) linkPtr);
    Tcl_DecrRefCount(linkPtr->varName);



    ckfree((char *) linkPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UpdateLinkedVar --
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

    /*
     * If the variable is being unset, then just re-create it (with a trace)
     * unless the whole interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
	if (Tcl_InterpDeleted(interp) || TclNamespaceDeleted(linkPtr->nsPtr)) {
	    Tcl_DecrRefCount(linkPtr->varName);
	    if (linkPtr->nsPtr) {
		TclNsDecrRefCount(linkPtr->nsPtr);
	    }
	    ckfree((char *) linkPtr);
	} else if (flags & TCL_TRACE_DESTROYED) {
	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		    TCL_GLOBAL_ONLY);
	    Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName),
		    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
		    |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);







|

<
<
<







275
276
277
278
279
280
281
282
283



284
285
286
287
288
289
290

    /*
     * If the variable is being unset, then just re-create it (with a trace)
     * unless the whole interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
	if (Tcl_InterpDeleted(interp)) {
	    Tcl_DecrRefCount(linkPtr->varName);



	    ckfree((char *) linkPtr);
	} else if (flags & TCL_TRACE_DESTROYED) {
	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		    TCL_GLOBAL_ONLY);
	    Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName),
		    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
		    |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);

Changes to generic/tclListObj.c.

1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
    }
    bytesNeeded += numElems;

    /*
     * Pass 2: copy into string rep buffer.
     */

    /*
     * We used to set the string length here, relying on a presumed
     * guarantee that the number of bytes TclScanElement() calls reported
     * to be needed was a precise count and not an over-estimate, so long
     * as the same flag values were passed to TclConvertElement().
     *
     * Then we saw [35a8f1c04a], where a bug in TclScanElement() caused
     * that guarantee to fail. Rather than trust there are no more bugs,
     * we set the length after the loop based on what was actually written,
     * an not on what was predicted.
     *
    listPtr->length = bytesNeeded - 1;
     *
     */

    listPtr->bytes = ckalloc((unsigned) bytesNeeded);
    dst = listPtr->bytes;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	dst += TclConvertElement(elem, length, dst, flagPtr[i]);
	*dst++ = ' ';
    }
    dst[-1] = '\0';

    /* Here is the safe setting of the string length. */
    listPtr->length = dst - 1 - listPtr->bytes;

    if (flagPtr != localFlags) {
	ckfree((char *) flagPtr);
    }
}

/*







<
<
<
<
<
<
<
<
<
<
<

<
<
<








<
<
<
|







1868
1869
1870
1871
1872
1873
1874











1875



1876
1877
1878
1879
1880
1881
1882
1883



1884
1885
1886
1887
1888
1889
1890
1891
    }
    bytesNeeded += numElems;

    /*
     * Pass 2: copy into string rep buffer.
     */












    listPtr->length = bytesNeeded - 1;



    listPtr->bytes = ckalloc((unsigned) bytesNeeded);
    dst = listPtr->bytes;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	dst += TclConvertElement(elem, length, dst, flagPtr[i]);
	*dst++ = ' ';
    }



    listPtr->bytes[listPtr->length] = '\0';

    if (flagPtr != localFlags) {
	ckfree((char *) flagPtr);
    }
}

/*

Changes to generic/tclLiteral.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * Function prototypes for static functions in this file:
 */

static int		AddLocalLiteralEntry(CompileEnv *envPtr,
			    Tcl_Obj *objPtr, int localHash);
static void		ExpandLocalLiteralArray(CompileEnv *envPtr);
static unsigned		HashString(const char *string, int length);
#ifdef TCL_COMPILE_DEBUG
static LiteralEntry *	LookupLiteralEntry(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
#endif
static void		RebuildLiteralTable(LiteralTable *tablePtr);

/*







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * Function prototypes for static functions in this file:
 */

static int		AddLocalLiteralEntry(CompileEnv *envPtr,
			    Tcl_Obj *objPtr, int localHash);
static void		ExpandLocalLiteralArray(CompileEnv *envPtr);
static unsigned int	HashString(const char *bytes, int length);
#ifdef TCL_COMPILE_DEBUG
static LiteralEntry *	LookupLiteralEntry(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
#endif
static void		RebuildLiteralTable(LiteralTable *tablePtr);

/*
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 *	The literal table is made ready for use.
 *
 *----------------------------------------------------------------------
 */

void
TclInitLiteralTable(
    LiteralTable *tablePtr)
				/* Pointer to table structure, which is
				 * supplied by the caller. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
    Tcl_Panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4",
	    TCL_SMALL_HASH_TABLE);
#endif







|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 *	The literal table is made ready for use.
 *
 *----------------------------------------------------------------------
 */

void
TclInitLiteralTable(
    register LiteralTable *tablePtr)
				/* Pointer to table structure, which is
				 * supplied by the caller. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
    Tcl_Panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4",
	    TCL_SMALL_HASH_TABLE);
#endif
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

    for (i=0 ; i<tablePtr->numBuckets ; i++) {
	entryPtr = tablePtr->buckets[i];
	while (entryPtr != NULL) {
	    objPtr = entryPtr->objPtr;
	    TclDecrRefCount(objPtr);
	    nextPtr = entryPtr->nextPtr;
	    ckfree((char *)entryPtr);
	    entryPtr = nextPtr;
	}
    }

    /*
     * Free up the table's bucket array if it was dynamically allocated.
     */

    if (tablePtr->buckets != tablePtr->staticBuckets) {
	ckfree((char *)tablePtr->buckets);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateLiteral --
 *
 *	Find, or if necessary create, an object in the interpreter's literal
 *	table that has a string representation matching the argument
 *	string. If nsPtr!=NULL then only literals stored for the namespace are
 *	considered.
 *
 * Results:
 *	The literal object. If it was created in this call *newPtr is set to
 *	1, else 0. NULL is returned if newPtr==NULL and no literal is found.
 *
 * Side effects:
 *	Increments the ref count of the global LiteralEntry since the caller

 *	now holds a reference. If LITERAL_ON_HEAP is set in flags, this
 *	function is given ownership of the string: if an object is created
 *	then its string representation is set directly from string, otherwise
 *	the string is freed. Typically, a caller sets LITERAL_ON_HEAP if
 *	"string" is an already heap-allocated buffer holding the result of
 *	backslash substitutions.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclCreateLiteral(
    Interp *iPtr,
    char *bytes,		/* The start of the string. Note that this is
				 * not a NUL-terminated string. */
    int length,			/* Number of bytes in the string. */
    unsigned hash,		/* The string's hash. If -1, it will be
				 * computed here. */
    int *newPtr,
    Namespace *nsPtr,
    int flags,
    LiteralEntry **globalPtrPtr)
{
    LiteralTable *globalTablePtr = &iPtr->literalTable;
    LiteralEntry *globalPtr;
    int globalHash;
    Tcl_Obj *objPtr;

    /*
     * Is it in the interpreter's global literal table?
     */

    if (hash == (unsigned) -1) {
	hash = HashString(bytes, length);
    }
    globalHash = (hash & globalTablePtr->mask);
    for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL;
	    globalPtr = globalPtr->nextPtr) {
	objPtr = globalPtr->objPtr;
	if (globalPtr->nsPtr == nsPtr) {
	    /*
	     * Literals should always have UTF-8 representations... but this
	     * is not guaranteed so we need to be careful anyway.
	     *
	     * https://stackoverflow.com/q/54337750/301832
	     */

	    int objLength;
	    char *objBytes = TclGetStringFromObj(objPtr, &objLength);

	    if ((objLength == length) && ((length == 0)
		    || ((objBytes[0] == bytes[0])
		    && (memcmp(objBytes, bytes, (unsigned) length) == 0)))) {
		/*
		 * A literal was found: return it
		 */

		if (newPtr) {
		    *newPtr = 0;
		}
		if (globalPtrPtr) {
		    *globalPtrPtr = globalPtr;
		}
		if (flags & LITERAL_ON_HEAP) {
		    ckfree(bytes);
		}
		globalPtr->refCount++;
		return objPtr;
	    }
	}
    }
    if (!newPtr) {
	if ((flags & LITERAL_ON_HEAP)) {
	    ckfree(bytes);
	}
	return NULL;
    }

    /*
     * The literal is new to the interpreter. Add it to the global literal
     * table.
     */

    TclNewObj(objPtr);
    Tcl_IncrRefCount(objPtr);
    if ((flags & LITERAL_ON_HEAP)) {
	objPtr->bytes = bytes;
	objPtr->length = length;
    } else {
	TclInitStringRep(objPtr, bytes, length);
    }

#ifdef TCL_COMPILE_DEBUG
    if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
	Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be",
		"TclRegisterLiteral", (length>60? 60 : length), bytes);
    }
#endif

    globalPtr = (LiteralEntry *)ckalloc(sizeof(LiteralEntry));
    globalPtr->objPtr = objPtr;
    globalPtr->refCount = 1;
    globalPtr->nsPtr = nsPtr;
    globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
    globalTablePtr->buckets[globalHash] = globalPtr;
    globalTablePtr->numEntries++;








|









|















|


|
>
|
|
|
<
|
|







|
<
|
|
<





|








|






|
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
<



|












|








|
|



|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177

178
179

180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201










202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

    for (i=0 ; i<tablePtr->numBuckets ; i++) {
	entryPtr = tablePtr->buckets[i];
	while (entryPtr != NULL) {
	    objPtr = entryPtr->objPtr;
	    TclDecrRefCount(objPtr);
	    nextPtr = entryPtr->nextPtr;
	    ckfree((char *) entryPtr);
	    entryPtr = nextPtr;
	}
    }

    /*
     * Free up the table's bucket array if it was dynamically allocated.
     */

    if (tablePtr->buckets != tablePtr->staticBuckets) {
	ckfree((char *) tablePtr->buckets);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateLiteral --
 *
 *	Find, or if necessary create, an object in the interpreter's literal
 *	table that has a string representation matching the argument
 *	string. If nsPtr!=NULL then only literals stored for the namespace are
 *	considered.
 *
 * Results:
 *	The literal object. If it was created in this call *newPtr is set to
 *      1, else 0. NULL is returned if newPtr==NULL and no literal is found.
 *
 * Side effects:
 *      Increments the ref count of the global LiteralEntry since the caller
 *      now holds a reference.
 *	If LITERAL_ON_HEAP is set in flags, this function is given ownership
 *	of the string: if an object is created then its string representation
 *	is set directly from string, otherwise the string is freed. Typically,

 *	a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
 *	buffer holding the result of backslash substitutions.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclCreateLiteral(
    Interp *iPtr,
    char *bytes,

    int length,
    unsigned int hash,       /* The string's hash. If -1, it will be computed here */

    int *newPtr,
    Namespace *nsPtr,
    int flags,
    LiteralEntry **globalPtrPtr)
{
    LiteralTable *globalTablePtr = &(iPtr->literalTable);
    LiteralEntry *globalPtr;
    int globalHash;
    Tcl_Obj *objPtr;

    /*
     * Is it in the interpreter's global literal table?
     */

    if (hash == (unsigned int) -1) {
	hash = HashString(bytes, length);
    }
    globalHash = (hash & globalTablePtr->mask);
    for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL;
	    globalPtr = globalPtr->nextPtr) {
	objPtr = globalPtr->objPtr;
	if ((globalPtr->nsPtr == nsPtr)










		&& (objPtr->length == length) && ((length == 0)
		|| ((objPtr->bytes[0] == bytes[0])
		&& (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
	    /*
	     * A literal was found: return it
	     */

	    if (newPtr) {
		*newPtr = 0;
	    }
	    if (globalPtrPtr) {
		*globalPtrPtr = globalPtr;
	    }
	    if (flags & LITERAL_ON_HEAP) {
		ckfree(bytes);
	    }
	    globalPtr->refCount++;
	    return objPtr;

	}
    }
    if (!newPtr) {
	if (flags & LITERAL_ON_HEAP) {
	    ckfree(bytes);
	}
	return NULL;
    }

    /*
     * The literal is new to the interpreter. Add it to the global literal
     * table.
     */

    TclNewObj(objPtr);
    Tcl_IncrRefCount(objPtr);
    if (flags & LITERAL_ON_HEAP) {
	objPtr->bytes = bytes;
	objPtr->length = length;
    } else {
	TclInitStringRep(objPtr, bytes, length);
    }

#ifdef TCL_COMPILE_DEBUG
    if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
	Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
		(length>60? 60 : length), bytes);
    }
#endif

    globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry));
    globalPtr->objPtr = objPtr;
    globalPtr->refCount = 1;
    globalPtr->nsPtr = nsPtr;
    globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
    globalTablePtr->buckets[globalHash] = globalPtr;
    globalTablePtr->numEntries++;

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
		    entryPtr=entryPtr->nextPtr) {
		if ((entryPtr == globalPtr) && (entryPtr->objPtr == objPtr)) {
		    found = 1;
		}
	    }
	}
	if (!found) {
	    Tcl_Panic("%s: literal \"%.*s\" wasn't global",
		    "TclRegisterLiteral", (length>60? 60 : length), bytes);
	}
    }
#endif /*TCL_COMPILE_DEBUG*/

#ifdef TCL_COMPILE_STATS
    iPtr->stats.numLiteralsCreated++;
    iPtr->stats.totalLitStringBytes += (double) (length + 1);







|
|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
		    entryPtr=entryPtr->nextPtr) {
		if ((entryPtr == globalPtr) && (entryPtr->objPtr == objPtr)) {
		    found = 1;
		}
	    }
	}
	if (!found) {
	    Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
		    (length>60? 60 : length), bytes);
	}
    }
#endif /*TCL_COMPILE_DEBUG*/

#ifdef TCL_COMPILE_STATS
    iPtr->stats.numLiteralsCreated++;
    iPtr->stats.totalLitStringBytes += (double) (length + 1);
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
 *	buffer holding the result of backslash substitutions.
 *
 *----------------------------------------------------------------------
 */

int
TclRegisterLiteral(
    void *ePtr,		/* Points to the CompileEnv in whose object
				 * array an object is found or created. */
    char *bytes,	/* Points to string for which to find or
				 * create an object in CompileEnv's object
				 * array. */
    int length,			/* Number of bytes in the string. If < 0, the
				 * string consists of all bytes up to the
				 * first null character. */
    int flags)			/* If LITERAL_ON_HEAP then the caller already
				 * malloc'd bytes and ownership is passed to
				 * this function. If LITERAL_NS_SCOPE then
				 * the literal should not be shared accross
				 * namespaces. */
{
    CompileEnv *envPtr = ePtr;
    Interp *iPtr = envPtr->iPtr;
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    LiteralEntry *globalPtr, *localPtr;
    Tcl_Obj *objPtr;
    unsigned hash;
    int localHash, objIndex, new;
    Namespace *nsPtr;

    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    hash = HashString(bytes, length);

    /*
     * Is the literal already in the CompileEnv's local literal array? If so,
     * just return its index.
     */

    localHash = (hash & localTablePtr->mask);
    for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL;
	    localPtr = localPtr->nextPtr) {
	objPtr = localPtr->objPtr;
	if ((objPtr->length == length) && ((length == 0)
		|| ((objPtr->bytes[0] == bytes[0])
		&& (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
	    if ((flags & LITERAL_ON_HEAP)) {
		ckfree(bytes);
	    }
	    objIndex = (localPtr - envPtr->literalArrayPtr);
#ifdef TCL_COMPILE_DEBUG
	    TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/








|

|








|


<

|


|




















|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
 *	buffer holding the result of backslash substitutions.
 *
 *----------------------------------------------------------------------
 */

int
TclRegisterLiteral(
    CompileEnv *envPtr,		/* Points to the CompileEnv in whose object
				 * array an object is found or created. */
    register char *bytes,	/* Points to string for which to find or
				 * create an object in CompileEnv's object
				 * array. */
    int length,			/* Number of bytes in the string. If < 0, the
				 * string consists of all bytes up to the
				 * first null character. */
    int flags)			/* If LITERAL_ON_HEAP then the caller already
				 * malloc'd bytes and ownership is passed to
				 * this function. If LITERAL_NS_SCOPE then
				 * the literal shouldnot be shared accross
				 * namespaces. */
{

    Interp *iPtr = envPtr->iPtr;
    LiteralTable *localTablePtr = &(envPtr->localLitTable);
    LiteralEntry *globalPtr, *localPtr;
    Tcl_Obj *objPtr;
    unsigned int hash;
    int localHash, objIndex, new;
    Namespace *nsPtr;

    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    hash = HashString(bytes, length);

    /*
     * Is the literal already in the CompileEnv's local literal array? If so,
     * just return its index.
     */

    localHash = (hash & localTablePtr->mask);
    for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL;
	    localPtr = localPtr->nextPtr) {
	objPtr = localPtr->objPtr;
	if ((objPtr->length == length) && ((length == 0)
		|| ((objPtr->bytes[0] == bytes[0])
		&& (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
	    if (flags & LITERAL_ON_HEAP) {
		ckfree(bytes);
	    }
	    objIndex = (localPtr - envPtr->literalArrayPtr);
#ifdef TCL_COMPILE_DEBUG
	    TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
 *----------------------------------------------------------------------
 */

static LiteralEntry *
LookupLiteralEntry(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    Tcl_Obj *objPtr)	/* Points to a Tcl object holding a literal
				 * that was previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr = &iPtr->literalTable;
    LiteralEntry *entryPtr;
    const char *bytes;
    int length, globalHash;

    bytes = TclGetStringFromObj(objPtr, &length);
    globalHash = (HashString(bytes, length) & globalTablePtr->mask);
    for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL;
	    entryPtr=entryPtr->nextPtr) {
	if (entryPtr->objPtr == objPtr) {







|




|
|
|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
 *----------------------------------------------------------------------
 */

static LiteralEntry *
LookupLiteralEntry(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    register Tcl_Obj *objPtr)	/* Points to a Tcl object holding a literal
				 * that was previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr = &(iPtr->literalTable);
    register LiteralEntry *entryPtr;
    char *bytes;
    int length, globalHash;

    bytes = TclGetStringFromObj(objPtr, &length);
    globalHash = (HashString(bytes, length) & globalTablePtr->mask);
    for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL;
	    entryPtr=entryPtr->nextPtr) {
	if (entryPtr->objPtr == objPtr) {
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
 *----------------------------------------------------------------------
 */

void
TclHideLiteral(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    CompileEnv *envPtr,/* Points to CompileEnv whose literal array
				 * contains the entry being hidden. */
    int index)			/* The index of the entry in the literal
				 * array. */
{
    LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    int localHash, length;
    const char *bytes;
    Tcl_Obj *newObjPtr;

    lPtr = &envPtr->literalArrayPtr[index];

    /*
     * To avoid unwanted sharing we need to copy the object and remove it from
     * the local and global literal tables. It still has a slot in the literal
     * array so it can be referred to by byte codes, but it will not be
     * matched by literal searches.
     */







|





|

|


|







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
 *----------------------------------------------------------------------
 */

void
TclHideLiteral(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    register CompileEnv *envPtr,/* Points to CompileEnv whose literal array
				 * contains the entry being hidden. */
    int index)			/* The index of the entry in the literal
				 * array. */
{
    LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
    LiteralTable *localTablePtr = &(envPtr->localLitTable);
    int localHash, length;
    char *bytes;
    Tcl_Obj *newObjPtr;

    lPtr = &(envPtr->literalArrayPtr[index]);

    /*
     * To avoid unwanted sharing we need to copy the object and remove it from
     * the local and global literal tables. It still has a slot in the literal
     * array so it can be referred to by byte codes, but it will not be
     * matched by literal searches.
     */
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
 *	literal object.
 *
 *----------------------------------------------------------------------
 */

int
TclAddLiteralObj(
    CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
				 * the object is to be inserted. */
    Tcl_Obj *objPtr,		/* The object to insert into the array. */
    LiteralEntry **litPtrPtr)	/* The location where the pointer to the new
				 * literal entry should be stored. May be
				 * NULL. */
{
    LiteralEntry *lPtr;
    int objIndex;

    if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
	ExpandLocalLiteralArray(envPtr);
    }
    objIndex = envPtr->literalArrayNext;
    envPtr->literalArrayNext++;

    lPtr = &envPtr->literalArrayPtr[objIndex];
    lPtr->objPtr = objPtr;
    Tcl_IncrRefCount(objPtr);
    lPtr->refCount = -1;	/* i.e., unused */
    lPtr->nextPtr = NULL;

    if (litPtrPtr) {
	*litPtrPtr = lPtr;







|






|








|







538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
 *	literal object.
 *
 *----------------------------------------------------------------------
 */

int
TclAddLiteralObj(
    register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
				 * the object is to be inserted. */
    Tcl_Obj *objPtr,		/* The object to insert into the array. */
    LiteralEntry **litPtrPtr)	/* The location where the pointer to the new
				 * literal entry should be stored. May be
				 * NULL. */
{
    register LiteralEntry *lPtr;
    int objIndex;

    if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
	ExpandLocalLiteralArray(envPtr);
    }
    objIndex = envPtr->literalArrayNext;
    envPtr->literalArrayNext++;

    lPtr = &(envPtr->literalArrayPtr[objIndex]);
    lPtr->objPtr = objPtr;
    Tcl_IncrRefCount(objPtr);
    lPtr->refCount = -1;	/* i.e., unused */
    lPtr->nextPtr = NULL;

    if (litPtrPtr) {
	*litPtrPtr = lPtr;
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
 *
 * Results:
 *	The index in the CompileEnv's literal array that references the
 *	literal.
 *
 * Side effects:
 *	Expands the literal array if necessary. May rebuild the hash bucket
 *	array of the CompileEnv's literal array if it becomes too large.
 *
 *----------------------------------------------------------------------
 */

static int
AddLocalLiteralEntry(
    CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
				 * the object is to be inserted. */
    Tcl_Obj *objPtr,		/* The literal to add to the CompileEnv. */
    int localHash)		/* Hash value for the literal's string. */
{
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    LiteralEntry *localPtr;
    int objIndex;

    objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);

    /*
     * Add the literal to the local table.







|






|

|


|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
 *
 * Results:
 *	The index in the CompileEnv's literal array that references the
 *	literal.
 *
 * Side effects:
 *	Expands the literal array if necessary. May rebuild the hash bucket
 *      array of the CompileEnv's literal array if it becomes too large.
 *
 *----------------------------------------------------------------------
 */

static int
AddLocalLiteralEntry(
    register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
				 * the object is to be inserted. */
    Tcl_Obj *objPtr,	        /* The literal to add to the CompileEnv. */
    int localHash)		/* Hash value for the literal's string. */
{
    register LiteralTable *localTablePtr = &(envPtr->localLitTable);
    LiteralEntry *localPtr;
    int objIndex;

    objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);

    /*
     * Add the literal to the local table.
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
		    found = 1;
		}
	    }
	}

	if (!found) {
	    bytes = Tcl_GetStringFromObj(objPtr, &length);
	    Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
		    "AddLocalLiteralEntry", (length>60? 60 : length), bytes);
	}
    }
#endif /*TCL_COMPILE_DEBUG*/

    return objIndex;
}








|
|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
		    found = 1;
		}
	    }
	}

	if (!found) {
	    bytes = Tcl_GetStringFromObj(objPtr, &length);
	    Tcl_Panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
		    (length>60? 60 : length), bytes);
	}
    }
#endif /*TCL_COMPILE_DEBUG*/

    return objIndex;
}

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
 *	The local literal table is updated to refer to the new entries.
 *
 *----------------------------------------------------------------------
 */

static void
ExpandLocalLiteralArray(
    CompileEnv *envPtr)/* Points to the CompileEnv whose object array
				 * must be enlarged. */
{
    /*
     * The current allocated local literal entries are stored between elements
     * 0 and (envPtr->literalArrayNext - 1) [inclusive].
     */

    LiteralTable *localTablePtr = &envPtr->localLitTable;
    int currElems = envPtr->literalArrayNext;
    size_t currBytes = (currElems * sizeof(LiteralEntry));
    LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
    LiteralEntry *newArrayPtr;
    int i;
    unsigned int newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX;

    if (currBytes == newSize) {
	Tcl_Panic("max size of Tcl literal array (%d literals) exceeded",
		currElems);
    }

    if (envPtr->mallocedLiteralArray) {
	newArrayPtr = (LiteralEntry *)ckrealloc(
		(char *)currArrayPtr, newSize);
    } else {
	/*
	 * envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must
	 * code a ckrealloc equivalent for ourselves.
	 */

	newArrayPtr = (LiteralEntry *)ckalloc(newSize);
	memcpy(newArrayPtr, currArrayPtr, currBytes);
	envPtr->mallocedLiteralArray = 1;
    }

    /*
     * Update the local literal table's bucket array.
     */







|







|













|




|

<
|







664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
 *	The local literal table is updated to refer to the new entries.
 *
 *----------------------------------------------------------------------
 */

static void
ExpandLocalLiteralArray(
    register CompileEnv *envPtr)/* Points to the CompileEnv whose object array
				 * must be enlarged. */
{
    /*
     * The current allocated local literal entries are stored between elements
     * 0 and (envPtr->literalArrayNext - 1) [inclusive].
     */

    LiteralTable *localTablePtr = &(envPtr->localLitTable);
    int currElems = envPtr->literalArrayNext;
    size_t currBytes = (currElems * sizeof(LiteralEntry));
    LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
    LiteralEntry *newArrayPtr;
    int i;
    unsigned int newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX;

    if (currBytes == newSize) {
	Tcl_Panic("max size of Tcl literal array (%d literals) exceeded",
		currElems);
    }

    if (envPtr->mallocedLiteralArray) {
	newArrayPtr = (LiteralEntry *) ckrealloc(
		(char *)currArrayPtr, newSize);
    } else {
	/*
	 * envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must
	 * code a ckrealloc equivalent for ourselves
	 */

	newArrayPtr = (LiteralEntry *) ckalloc(newSize);
	memcpy(newArrayPtr, currArrayPtr, currBytes);
	envPtr->mallocedLiteralArray = 1;
    }

    /*
     * Update the local literal table's bucket array.
     */
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
 *----------------------------------------------------------------------
 */

void
TclReleaseLiteral(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    Tcl_Obj *objPtr)	/* Points to a literal object that was
				 * previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr;
    LiteralEntry *entryPtr, *prevPtr;
    const char *bytes;
    int length, index;

    if (iPtr == NULL) {
	goto done;
    }

    globalTablePtr = &iPtr->literalTable;
    bytes = TclGetStringFromObj(objPtr, &length);
    index = (HashString(bytes, length) & globalTablePtr->mask);

    /*
     * Check to see if the object is in the global literal table and remove
     * this reference. The object may not be in the table if it is a hidden
     * local literal.







|




|
|
|


<
<
<
<
<







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762





763
764
765
766
767
768
769
 *----------------------------------------------------------------------
 */

void
TclReleaseLiteral(
    Tcl_Interp *interp,		/* Interpreter for which objPtr was created to
				 * hold a literal. */
    register Tcl_Obj *objPtr)	/* Points to a literal object that was
				 * previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr = &(iPtr->literalTable);
    register LiteralEntry *entryPtr, *prevPtr;
    char *bytes;
    int length, index;






    bytes = TclGetStringFromObj(objPtr, &length);
    index = (HashString(bytes, length) & globalTablePtr->mask);

    /*
     * Check to see if the object is in the global literal table and remove
     * this reference. The object may not be in the table if it is a hidden
     * local literal.
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

	    if (entryPtr->refCount == 0) {
		if (prevPtr == NULL) {
		    globalTablePtr->buckets[index] = entryPtr->nextPtr;
		} else {
		    prevPtr->nextPtr = entryPtr->nextPtr;
		}
		ckfree((char *)entryPtr);
		globalTablePtr->numEntries--;

		TclDecrRefCount(objPtr);

#ifdef TCL_COMPILE_STATS
		iPtr->stats.currentLitStringBytes -= (double) (length + 1);
#endif /*TCL_COMPILE_STATS*/
	    }
	    break;
	}
    }

    /*
     * Remove the reference corresponding to the local literal table entry.
     */

    done:
    Tcl_DecrRefCount(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * HashString --







|
















<







782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805

806
807
808
809
810
811
812

	    if (entryPtr->refCount == 0) {
		if (prevPtr == NULL) {
		    globalTablePtr->buckets[index] = entryPtr->nextPtr;
		} else {
		    prevPtr->nextPtr = entryPtr->nextPtr;
		}
		ckfree((char *) entryPtr);
		globalTablePtr->numEntries--;

		TclDecrRefCount(objPtr);

#ifdef TCL_COMPILE_STATS
		iPtr->stats.currentLitStringBytes -= (double) (length + 1);
#endif /*TCL_COMPILE_STATS*/
	    }
	    break;
	}
    }

    /*
     * Remove the reference corresponding to the local literal table entry.
     */


    Tcl_DecrRefCount(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * HashString --
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned int
HashString(
    const char *bytes,	/* String for which to compute hash value. */
    int length)			/* Number of bytes in the string. */
{
    unsigned int result;
    int i;

    /*
     * I tried a zillion different hash functions and asked many other people
     * for advice. Many people had their own favorite functions, all
     * different, but no-one had much idea why they were good ones. I chose
     * the one below (multiply by 9 and add new character) because of the
     * following reasons:
     *
     * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
     *    multiplying by 9 is just about as good.
     * 2. Times-9 is (shift-left-3) plus (old). This means that each
     *    character's bits hang around in the low-order bits of the hash value
     *    for ever, plus they spread fairly rapidly up to the high-order bits
     *    to fill out the hash value. This seems works well both for decimal
     *    and non-decimal strings.
     *
     * Note that this function is very weak against malicious strings; it's
     * very easy to generate multiple keys that have the same hashcode. On the
     * other hand, that hardly ever actually occurs and this function *is*
     * very cheap, even by comparison with industry-standard hashes like FNV.
     * If real strength of hash is required though, use a custom hash based on
     * Bob Jenkins's lookup3(), but be aware that it's significantly slower.
     * Tcl scripts tend to not have a big issue in this area, and literals
     * mostly aren't looked up by name anyway.
     *
     * See also HashStringKey in tclHash.c.
     * See also TclObjHashKey in tclObj.c.
     *
     * See [tcl-Feature Request #2958832]
     */

    result = 0;
    for (i=0 ; i<length ; i++) {
	result += (result<<3) + bytes[i];
    }
    return result;







|


|
|









|

|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<







821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847














848
849
850
851
852
853
854
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned int
HashString(
    register const char *bytes,	/* String for which to compute hash value. */
    int length)			/* Number of bytes in the string. */
{
    register unsigned int result;
    register int i;

    /*
     * I tried a zillion different hash functions and asked many other people
     * for advice. Many people had their own favorite functions, all
     * different, but no-one had much idea why they were good ones. I chose
     * the one below (multiply by 9 and add new character) because of the
     * following reasons:
     *
     * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
     *	  multiplying by 9 is just about as good.
     * 2. Times-9 is (shift-left-3) plus (old). This means that each
     *	  character's bits hang around in the low-order bits of the hash value
     *	  for ever, plus they spread fairly rapidly up to the high-order bits
     *	  to fill out the hash value. This seems works well both for decimal
     *	  and non-decimal strings.














     */

    result = 0;
    for (i=0 ; i<length ; i++) {
	result += (result<<3) + bytes[i];
    }
    return result;
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
 *	Memory gets reallocated and entries get rehashed into new buckets.
 *
 *----------------------------------------------------------------------
 */

static void
RebuildLiteralTable(
    LiteralTable *tablePtr)
				/* Local or global table to enlarge. */
{
    LiteralEntry **oldBuckets;
    LiteralEntry **oldChainPtr, **newChainPtr;
    LiteralEntry *entryPtr;
    LiteralEntry **bucketPtr;
    const char *bytes;
    unsigned int oldSize;
    int count, index, length;

    oldSize = tablePtr->numBuckets;
    oldBuckets = tablePtr->buckets;

    /*







|



|
|

|







870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
 *	Memory gets reallocated and entries get rehashed into new buckets.
 *
 *----------------------------------------------------------------------
 */

static void
RebuildLiteralTable(
    register LiteralTable *tablePtr)
				/* Local or global table to enlarge. */
{
    LiteralEntry **oldBuckets;
    register LiteralEntry **oldChainPtr, **newChainPtr;
    register LiteralEntry *entryPtr;
    LiteralEntry **bucketPtr;
    char *bytes;
    unsigned int oldSize;
    int count, index, length;

    oldSize = tablePtr->numBuckets;
    oldBuckets = tablePtr->buckets;

    /*
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
	 * with what we have.
	 */

	return;
    }

    tablePtr->numBuckets *= 4;
    tablePtr->buckets = (LiteralEntry **)ckalloc(
	    tablePtr->numBuckets * sizeof(LiteralEntry *));
    for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets;
	    count>0 ; count--, newChainPtr++) {
	*newChainPtr = NULL;
    }
    tablePtr->rebuildSize *= 4;
    tablePtr->mask = (tablePtr->mask << 2) + 3;

    /*
     * Rehash all of the existing entries into the new bucket array.
     */

    for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
	for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
	    bytes = TclGetStringFromObj(entryPtr->objPtr, &length);
	    index = (HashString(bytes, length) & tablePtr->mask);

	    *oldChainPtr = entryPtr->nextPtr;
	    bucketPtr = &tablePtr->buckets[index];
	    entryPtr->nextPtr = *bucketPtr;
	    *bucketPtr = entryPtr;
	}
    }

    /*
     * Free up the old bucket array, if it was dynamically allocated.
     */

    if (oldBuckets != tablePtr->staticBuckets) {
	ckfree((char *)oldBuckets);
    }
}

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
 *







|
|

















|










|







900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	 * with what we have.
	 */

	return;
    }

    tablePtr->numBuckets *= 4;
    tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned)
	    (tablePtr->numBuckets * sizeof(LiteralEntry *)));
    for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets;
	    count>0 ; count--, newChainPtr++) {
	*newChainPtr = NULL;
    }
    tablePtr->rebuildSize *= 4;
    tablePtr->mask = (tablePtr->mask << 2) + 3;

    /*
     * Rehash all of the existing entries into the new bucket array.
     */

    for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
	for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
	    bytes = TclGetStringFromObj(entryPtr->objPtr, &length);
	    index = (HashString(bytes, length) & tablePtr->mask);

	    *oldChainPtr = entryPtr->nextPtr;
	    bucketPtr = &(tablePtr->buckets[index]);
	    entryPtr->nextPtr = *bucketPtr;
	    *bucketPtr = entryPtr;
	}
    }

    /*
     * Free up the old bucket array, if it was dynamically allocated.
     */

    if (oldBuckets != tablePtr->staticBuckets) {
	ckfree((char *) oldBuckets);
    }
}

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
 *
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
char *
TclLiteralStats(
    LiteralTable *tablePtr)	/* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
    int count[NUM_COUNTERS], overflow, i, j;
    double average, tmp;
    LiteralEntry *entryPtr;
    char *result, *p;

    /*
     * Compute a histogram of bucket usage. For each bucket chain i, j is the
     * number of entries in the chain.
     */








|







960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
char *
TclLiteralStats(
    LiteralTable *tablePtr)	/* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
    int count[NUM_COUNTERS], overflow, i, j;
    double average, tmp;
    register LiteralEntry *entryPtr;
    char *result, *p;

    /*
     * Compute a histogram of bucket usage. For each bucket chain i, j is the
     * number of entries in the chain.
     */

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
	average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
    }

    /*
     * Print out the histogram and a few other pieces of information.
     */

    result = (char *)ckalloc(NUM_COUNTERS*60 + 300);
    sprintf(result, "%d entries in table, %d buckets\n",
	    tablePtr->numEntries, tablePtr->numBuckets);
    p = result + strlen(result);
    for (i=0 ; i<NUM_COUNTERS ; i++) {
	sprintf(p, "number of buckets with %d entries: %d\n",
		i, count[i]);
	p += strlen(p);







|







992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
	average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
    }

    /*
     * Print out the histogram and a few other pieces of information.
     */

    result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
    sprintf(result, "%d entries in table, %d buckets\n",
	    tablePtr->numEntries, tablePtr->numBuckets);
    p = result + strlen(result);
    for (i=0 ; i<NUM_COUNTERS ; i++) {
	sprintf(p, "number of buckets with %d entries: %d\n",
		i, count[i]);
	p += strlen(p);
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
 */

void
TclVerifyLocalLiteralTable(
    CompileEnv *envPtr)		/* Points to CompileEnv whose literal table is
				 * to be validated. */
{
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    LiteralEntry *localPtr;
    char *bytes;
    int i;
    int length, count;

    count = 0;
    for (i=0 ; i<localTablePtr->numBuckets ; i++) {
	for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
		localPtr=localPtr->nextPtr) {
	    count++;
	    if (localPtr->refCount != -1) {
		bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
		Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d",
			"TclVerifyLocalLiteralTable",
			(length>60? 60 : length), bytes, localPtr->refCount);
	    }
	    if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
		    localPtr->objPtr) == NULL) {
		bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
		Tcl_Panic("%s: local literal \"%.*s\" is not global",
			"TclVerifyLocalLiteralTable", (length>60? 60 : length), bytes);
	    }
	    if (localPtr->objPtr->bytes == NULL) {
		Tcl_Panic("%s: literal has NULL string rep",
			"TclVerifyLocalLiteralTable");
	    }
	}
    }
    if (count != localTablePtr->numEntries) {
	Tcl_Panic("%s: local literal table had %d entries, should be %d",
		"TclVerifyLocalLiteralTable", count,
		localTablePtr->numEntries);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclVerifyGlobalLiteralTable --







|
|

|









|
<





|
|


<
|




|
<
|







1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1074
 */

void
TclVerifyLocalLiteralTable(
    CompileEnv *envPtr)		/* Points to CompileEnv whose literal table is
				 * to be validated. */
{
    register LiteralTable *localTablePtr = &(envPtr->localLitTable);
    register LiteralEntry *localPtr;
    char *bytes;
    register int i;
    int length, count;

    count = 0;
    for (i=0 ; i<localTablePtr->numBuckets ; i++) {
	for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
		localPtr=localPtr->nextPtr) {
	    count++;
	    if (localPtr->refCount != -1) {
		bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
		Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",

			(length>60? 60 : length), bytes, localPtr->refCount);
	    }
	    if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
		    localPtr->objPtr) == NULL) {
		bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
		Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
			(length>60? 60 : length), bytes);
	    }
	    if (localPtr->objPtr->bytes == NULL) {

		Tcl_Panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
	    }
	}
    }
    if (count != localTablePtr->numEntries) {
	Tcl_Panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",

		count, localTablePtr->numEntries);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclVerifyGlobalLiteralTable --
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
 */

void
TclVerifyGlobalLiteralTable(
    Interp *iPtr)		/* Points to interpreter whose global literal
				 * table is to be validated. */
{
    LiteralTable *globalTablePtr = &iPtr->literalTable;
    LiteralEntry *globalPtr;
    char *bytes;
    int i;
    int length, count;

    count = 0;
    for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
	for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
		globalPtr=globalPtr->nextPtr) {
	    count++;
	    if (globalPtr->refCount < 1) {
		bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
		Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
			"TclVerifyGlobalLiteralTable",
			(length>60? 60 : length), bytes, globalPtr->refCount);
	    }
	    if (globalPtr->objPtr->bytes == NULL) {
		Tcl_Panic("%s: literal has NULL string rep",
			"TclVerifyGlobalLiteralTable");
	    }
	}
    }
    if (count != globalTablePtr->numEntries) {
	Tcl_Panic("%s: global literal table had %d entries, should be %d",
		"TclVerifyGlobalLiteralTable", count,
		globalTablePtr->numEntries);
    }
}
#endif /*TCL_COMPILE_DEBUG*/

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|
|

|









|
<



<
|




|
<
|











1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108

1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
 */

void
TclVerifyGlobalLiteralTable(
    Interp *iPtr)		/* Points to interpreter whose global literal
				 * table is to be validated. */
{
    register LiteralTable *globalTablePtr = &(iPtr->literalTable);
    register LiteralEntry *globalPtr;
    char *bytes;
    register int i;
    int length, count;

    count = 0;
    for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
	for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
		globalPtr=globalPtr->nextPtr) {
	    count++;
	    if (globalPtr->refCount < 1) {
		bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
		Tcl_Panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",

			(length>60? 60 : length), bytes, globalPtr->refCount);
	    }
	    if (globalPtr->objPtr->bytes == NULL) {

		Tcl_Panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
	    }
	}
    }
    if (count != globalTablePtr->numEntries) {
	Tcl_Panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",

		count, globalTablePtr->numEntries);
    }
}
#endif /*TCL_COMPILE_DEBUG*/

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclLoad.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

typedef struct LoadedPackage {
    char *fileName;		/* Name of the file from which the package was
				 * loaded. An empty string means the package
				 * is loaded statically. Malloc-ed. */
    char *packageName;		/* Name of package prefix for the package,
				 * properly capitalized (first letter UC,
				 * others LC), as in "Net".
				 * Malloc-ed. */
    Tcl_LoadHandle loadHandle;	/* Token for the loaded file which should be
				 * passed to (*unLoadProcPtr)() when the file
				 * is no longer needed. If fileName is NULL,
				 * then this field is irrelevant. */
    Tcl_PackageInitProc *initProc;
				/* Initialization function to call to







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

typedef struct LoadedPackage {
    char *fileName;		/* Name of the file from which the package was
				 * loaded. An empty string means the package
				 * is loaded statically. Malloc-ed. */
    char *packageName;		/* Name of package prefix for the package,
				 * properly capitalized (first letter UC,
				 * others LC), no "_", as in "Net".
				 * Malloc-ed. */
    Tcl_LoadHandle loadHandle;	/* Token for the loaded file which should be
				 * passed to (*unLoadProcPtr)() when the file
				 * is no longer needed. If fileName is NULL,
				 * then this field is irrelevant. */
    Tcl_PackageInitProc *initProc;
				/* Initialization function to call to
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
		if (ipPtr->pkgPtr == defaultPtr) {
		    ipFirstPtr = ipFirstPtr->nextPtr;
		} else {
		    InterpPackage *ipPrevPtr;

		    for (ipPrevPtr = ipPtr; ipPtr != NULL;
			    ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
			if (ipPtr->pkgPtr == defaultPtr) {
			    ipPrevPtr->nextPtr = ipPtr->nextPtr;
			    break;
			}
		    }
		}
		Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
			(ClientData) ipFirstPtr);







|







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
		if (ipPtr->pkgPtr == defaultPtr) {
		    ipFirstPtr = ipFirstPtr->nextPtr;
		} else {
		    InterpPackage *ipPrevPtr;

		    for (ipPrevPtr = ipPtr; ipPtr != NULL;
			    ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
			if (ipPtr->pkgPtr == pkgPtr) {
			    ipPrevPtr->nextPtr = ipPtr->nextPtr;
			    break;
			}
		    }
		}
		Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
			(ClientData) ipFirstPtr);

Changes to generic/tclNamesp.c.

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
	     * get killed later, avoiding mem leaks.
	     */

	    nsPtr->flags &= ~(NS_DYING|NS_KILLED);
	}
    }
}

int
TclNamespaceDeleted(
    Namespace *nsPtr)
{
    return (nsPtr->flags & NS_DYING) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclTeardownNamespace --
 *
 *	Used internally to dismantle and unlink a namespace when it is







<
<
<
<
<
<
<







1056
1057
1058
1059
1060
1061
1062







1063
1064
1065
1066
1067
1068
1069
	     * get killed later, avoiding mem leaks.
	     */

	    nsPtr->flags &= ~(NS_DYING|NS_KILLED);
	}
    }
}








/*
 *----------------------------------------------------------------------
 *
 * TclTeardownNamespace --
 *
 *	Used internally to dismantle and unlink a namespace when it is
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
     */

    ckfree(nsPtr->name);
    ckfree(nsPtr->fullName);

    ckfree((char *) nsPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclNsDecrRefCount --
 *
 *      Drops a reference to a namespace and frees it if the namespace has
 *      been deleted and the last reference has just been dropped.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
TclNsDecrRefCount(
    Namespace *nsPtr)
{
    nsPtr->refCount--;
    if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
        NamespaceFree(nsPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Export --
 *
 *	Makes all the commands matching a pattern available to later be







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1232
1233
1234
1235
1236
1237
1238



























1239
1240
1241
1242
1243
1244
1245
     */

    ckfree(nsPtr->name);
    ckfree(nsPtr->fullName);

    ckfree((char *) nsPtr);
}




























/*
 *----------------------------------------------------------------------
 *
 * Tcl_Export --
 *
 *	Makes all the commands matching a pattern available to later be

Changes to generic/tclObj.c.

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
	(objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
    } else { \
	if ((bignum).alloc > 0x7fff) { \
	    mp_shrink(&(bignum)); \
	} \
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
	(objPtr)->internalRep.ptrAndLongRep.value = ( (mp_isneg(&bignum) << 30) \
		| ((bignum).alloc << 15) | ((bignum).used)); \
    }

#define UNPACK_BIGNUM(objPtr, bignum) \
    if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
	(bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
    } else { \







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
	(objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
    } else { \
	if ((bignum).alloc > 0x7fff) { \
	    mp_shrink(&(bignum)); \
	} \
	(objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
	(objPtr)->internalRep.ptrAndLongRep.value = ( ((bignum).sign << 30) \
		| ((bignum).alloc << 15) | ((bignum).used)); \
    }

#define UNPACK_BIGNUM(objPtr, bignum) \
    if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
	(bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
    } else { \
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

/*
 * The structure below defines the Tcl obj hash key type.
 */

Tcl_HashKeyType tclObjHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    TCL_HASH_KEY_DIRECT_COMPARE,/* allows compare keys by pointers */
    TclHashObjKey,		/* hashKeyProc */
    TclCompareObjKeys,		/* compareKeysProc */
    AllocObjEntry,		/* allocEntryProc */
    TclFreeObjEntry		/* freeEntryProc */
};

/*







|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

/*
 * The structure below defines the Tcl obj hash key type.
 */

Tcl_HashKeyType tclObjHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    0,				/* flags */
    TclHashObjKey,		/* hashKeyProc */
    TclCompareObjKeys,		/* compareKeysProc */
    AllocObjEntry,		/* allocEntryProc */
    TclFreeObjEntry		/* freeEntryProc */
};

/*
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
	     * long range get auto-narrowed to tclIntType, while all the
	     * values in the unsigned long range will fit in a long.
	     */

	    mp_int big;

	    UNPACK_BIGNUM(objPtr, big);
	    if ((size_t)(big.used) <= (CHAR_BIT * sizeof(long) + MP_DIGIT_BIT - 1)
		    / MP_DIGIT_BIT) {
		unsigned long value = 0, numBytes = sizeof(long);
		long scratch;
		unsigned char *bytes = (unsigned char *)&scratch;
		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (mp_isneg(&big)) {
			*longPtr = - (long) value;
		    } else {
			*longPtr = (long) value;
		    }
		    return TCL_OK;
		}
	    }







|
|







|







2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
	     * long range get auto-narrowed to tclIntType, while all the
	     * values in the unsigned long range will fit in a long.
	     */

	    mp_int big;

	    UNPACK_BIGNUM(objPtr, big);
	    if ((size_t)(big.used) <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1)
		    / DIGIT_BIT) {
		unsigned long value = 0, numBytes = sizeof(long);
		long scratch;
		unsigned char *bytes = (unsigned char *)&scratch;
		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (big.sign) {
			*longPtr = - (long) value;
		    } else {
			*longPtr = (long) value;
		    }
		    return TCL_OK;
		}
	    }
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
	     * Tcl_WideInt, even when auto-narrowing is enabled.
	     */

	    mp_int big;

	    UNPACK_BIGNUM(objPtr, big);
	    if ((size_t)(big.used) <= (CHAR_BIT * sizeof(Tcl_WideInt)
		     + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT) {
		Tcl_WideUInt value = 0;
		unsigned long numBytes = sizeof(Tcl_WideInt);
		Tcl_WideInt scratch;
		unsigned char *bytes = (unsigned char *) &scratch;

		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (mp_isneg(&big)) {
			*wideIntPtr = - (Tcl_WideInt) value;
		    } else {
			*wideIntPtr = (Tcl_WideInt) value;
		    }
		    return TCL_OK;
		}
	    }







|









|







3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
	     * Tcl_WideInt, even when auto-narrowing is enabled.
	     */

	    mp_int big;

	    UNPACK_BIGNUM(objPtr, big);
	    if ((size_t)(big.used) <= (CHAR_BIT * sizeof(Tcl_WideInt)
		     + DIGIT_BIT - 1) / DIGIT_BIT) {
		Tcl_WideUInt value = 0;
		unsigned long numBytes = sizeof(Tcl_WideInt);
		Tcl_WideInt scratch;
		unsigned char *bytes = (unsigned char *) &scratch;

		if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
		    while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		    }
		    if (big.sign) {
			*wideIntPtr = - (Tcl_WideInt) value;
		    } else {
			*wideIntPtr = (Tcl_WideInt) value;
		    }
		    return TCL_OK;
		}
	    }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
    Tcl_Obj *objPtr,		/* Object to set */
    mp_int *bignumValue)	/* Value to store */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
    }
    if ((size_t)(bignumValue->used)
	    <= (CHAR_BIT * sizeof(long) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT) {
	unsigned long value = 0, numBytes = sizeof(long);
	long scratch;
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForLong;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(unsigned long)0) >> 1) + mp_isneg(bignumValue))) {
	    goto tooLargeForLong;
	}
	if (mp_isneg(bignumValue)) {
	    TclSetLongObj(objPtr, -(long)value);
	} else {
	    TclSetLongObj(objPtr, (long)value);
	}
	mp_clear(bignumValue);
	return;
    }
  tooLargeForLong:
#ifndef NO_WIDE_TYPE
    if ((size_t)(bignumValue->used)
	    <= (CHAR_BIT * sizeof(Tcl_WideInt) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT) {
	Tcl_WideUInt value = 0;
	unsigned long numBytes = sizeof(Tcl_WideInt);
	Tcl_WideInt scratch;
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForWide;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(Tcl_WideUInt)0) >> 1) + mp_isneg(bignumValue))) {
	    goto tooLargeForWide;
	}
	if (mp_isneg(bignumValue)) {
	    TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
	} else {
	    TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
	}
	mp_clear(bignumValue);
	return;
    }







|









|


|










|










|


|







3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
    Tcl_Obj *objPtr,		/* Object to set */
    mp_int *bignumValue)	/* Value to store */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
    }
    if ((size_t)(bignumValue->used)
	    <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) {
	unsigned long value = 0, numBytes = sizeof(long);
	long scratch;
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForLong;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
	    goto tooLargeForLong;
	}
	if (bignumValue->sign) {
	    TclSetLongObj(objPtr, -(long)value);
	} else {
	    TclSetLongObj(objPtr, (long)value);
	}
	mp_clear(bignumValue);
	return;
    }
  tooLargeForLong:
#ifndef NO_WIDE_TYPE
    if ((size_t)(bignumValue->used)
	    <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
	Tcl_WideUInt value = 0;
	unsigned long numBytes = sizeof(Tcl_WideInt);
	Tcl_WideInt scratch;
	unsigned char *bytes = (unsigned char *)&scratch;
	if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
	    goto tooLargeForWide;
	}
	while (numBytes-- > 0) {
	    value = (value << CHAR_BIT) | *bytes++;
	}
	if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) {
	    goto tooLargeForWide;
	}
	if (bignumValue->sign) {
	    TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
	} else {
	    TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
	}
	mp_clear(bignumValue);
	return;
    }
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927


3928
3929
3930
3931
3932
3933
3934
    Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
    Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
    register CONST char *p1, *p2;
    register int l1, l2;

    /*
     * If the object pointers are the same then they match.
     * OPT: this comparison was moved to the caller

       if (objPtr1 == objPtr2) return 1;
    */



    /*
     * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
     * in a register.
     */

    p1 = TclGetString(objPtr1);







|

|
<
>
>







3917
3918
3919
3920
3921
3922
3923
3924
3925
3926

3927
3928
3929
3930
3931
3932
3933
3934
3935
    Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
    Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
    register CONST char *p1, *p2;
    register int l1, l2;

    /*
     * If the object pointers are the same then they match.
     */

    if (objPtr1 == objPtr2) {

	return 1;
    }

    /*
     * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
     * in a register.
     */

    p1 = TclGetString(objPtr1);

Changes to generic/tclParse.c.

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
static inline int	CommandComplete(const char *script, int numBytes);
static int		ParseComment(const char *src, int numBytes,
			    Tcl_Parse *parsePtr);
static int		ParseTokens(const char *src, int numBytes, int mask,
			    int flags, Tcl_Parse *parsePtr);
static int		ParseWhiteSpace(const char *src, int numBytes,
			    int *incompletePtr, char *typePtr);
static int		ParseHex(const char *src, int numBytes,
			    int *resultPtr);

/*
 *----------------------------------------------------------------------
 *
 * TclParseInit --
 *
 *	Initialize the fields of a Tcl_Parse struct.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The Tcl_Parse struct pointed to by parsePtr gets initialized.
 *
 *----------------------------------------------------------------------
 */

void
TclParseInit(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting */







<
<






|


|


|







172
173
174
175
176
177
178


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
static inline int	CommandComplete(const char *script, int numBytes);
static int		ParseComment(const char *src, int numBytes,
			    Tcl_Parse *parsePtr);
static int		ParseTokens(const char *src, int numBytes, int mask,
			    int flags, Tcl_Parse *parsePtr);
static int		ParseWhiteSpace(const char *src, int numBytes,
			    int *incompletePtr, char *typePtr);



/*
 *----------------------------------------------------------------------
 *
 * TclParseInit --
 *
 * 	Initialize the fields of a Tcl_Parse struct.
 *
 * Results:
 * 	None.
 *
 * Side effects:
 * 	The Tcl_Parse struct pointed to by parsePtr gets initialized.
 *
 *----------------------------------------------------------------------
 */

void
TclParseInit(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting */
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280




281
282
283
284
285
286
287
				 * the script consists of all bytes up to the
				 * first null character. */
    int nested,			/* Non-zero means this is a nested command:
				 * close bracket should be considered a
				 * command terminator. If zero, then close
				 * bracket has no special meaning. */
    register Tcl_Parse *parsePtr)
				/* Structure to fill in with information about
				 * the parsed command; any previous
				 * information in the structure is ignored. */
{
    register const char *src;	/* Points to current character in the
				 * command. */
    char type;			/* Result returned by CHAR_TYPE(*src). */
    Tcl_Token *tokenPtr;	/* Pointer to token being filled in. */
    int wordIndex;		/* Index of word token for current word. */
    int terminators;		/* CHAR_TYPE bits that indicate the end of a
				 * command. */
    const char *termPtr;	/* Set by Tcl_ParseBraces/QuotedString to
				 * point to char after terminating one. */
    int scanned;

    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }
    TclParseInit(interp, start, numBytes, parsePtr);
    if ((start == NULL) && (numBytes != 0)) {
	if (interp != NULL) {
	    Tcl_SetResult(interp, "can't parse a NULL pointer", TCL_STATIC);
	}
	return TCL_ERROR;
    }




    parsePtr->commentStart = NULL;
    parsePtr->commentSize = 0;
    parsePtr->commandStart = NULL;
    parsePtr->commandSize = 0;
    if (nested != 0) {
	terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
    } else {







|














<
<
<
<






>
>
>
>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268




269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
				 * the script consists of all bytes up to the
				 * first null character. */
    int nested,			/* Non-zero means this is a nested command:
				 * close bracket should be considered a
				 * command terminator. If zero, then close
				 * bracket has no special meaning. */
    register Tcl_Parse *parsePtr)
    				/* Structure to fill in with information about
				 * the parsed command; any previous
				 * information in the structure is ignored. */
{
    register const char *src;	/* Points to current character in the
				 * command. */
    char type;			/* Result returned by CHAR_TYPE(*src). */
    Tcl_Token *tokenPtr;	/* Pointer to token being filled in. */
    int wordIndex;		/* Index of word token for current word. */
    int terminators;		/* CHAR_TYPE bits that indicate the end of a
				 * command. */
    const char *termPtr;	/* Set by Tcl_ParseBraces/QuotedString to
				 * point to char after terminating one. */
    int scanned;





    if ((start == NULL) && (numBytes != 0)) {
	if (interp != NULL) {
	    Tcl_SetResult(interp, "can't parse a NULL pointer", TCL_STATIC);
	}
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
    }
    TclParseInit(interp, start, numBytes, parsePtr);
    parsePtr->commentStart = NULL;
    parsePtr->commentSize = 0;
    parsePtr->commandStart = NULL;
    parsePtr->commandSize = 0;
    if (nested != 0) {
	terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
    } else {
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
		    parsePtr->numTokens = wordIndex;
		} else {
		    /*
		     * Recalculate the number of Tcl_Tokens needed to store
		     * tokens representing the expanded list.
		     */

		    const char *listStart;
		    int growthNeeded = wordIndex + 2*elemCount
			    - parsePtr->numTokens;

		    parsePtr->numWords += elemCount - 1;
		    if (growthNeeded > 0) {
			TclGrowParseTokenArray(parsePtr, growthNeeded);
			tokenPtr = &parsePtr->tokenPtr[wordIndex];
		    }
		    parsePtr->numTokens = wordIndex + 2*elemCount;








|


<







492
493
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
		    parsePtr->numTokens = wordIndex;
		} else {
		    /*
		     * Recalculate the number of Tcl_Tokens needed to store
		     * tokens representing the expanded list.
		     */

		    CONST char *listStart;
		    int growthNeeded = wordIndex + 2*elemCount
			    - parsePtr->numTokens;

		    parsePtr->numWords += elemCount - 1;
		    if (growthNeeded > 0) {
			TclGrowParseTokenArray(parsePtr, growthNeeded);
			tokenPtr = &parsePtr->tokenPtr[wordIndex];
		    }
		    parsePtr->numTokens = wordIndex + 2*elemCount;

712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
	    }
	    if (--numBytes == 0) {
		break;
	    }
	    if (p[1] != '\n') {
		break;
	    }
	    p += 2;
	    if (--numBytes == 0) {
		*incompletePtr = 1;
		break;
	    }
	    continue;
	}
	break;







|







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
	    }
	    if (--numBytes == 0) {
		break;
	    }
	    if (p[1] != '\n') {
		break;
	    }
	    p+=2;
	    if (--numBytes == 0) {
		*incompletePtr = 1;
		break;
	    }
	    continue;
	}
	break;
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
    } while (numBytes && (*p == '\n') && (p++, --numBytes));
    return (p-src);
}

/*
 *----------------------------------------------------------------------
 *
 * ParseHex --
 *
 *	Scans a hexadecimal number as a Tcl_UniChar value (e.g., for parsing
 *	\x and \u escape sequences). At most numBytes bytes are scanned.
 *
 * Results:
 *	The numeric value is stored in *resultPtr. Returns the number of bytes
 *	consumed.
 *
 * Notes:
 *	Relies on the following properties of the ASCII character set, with
 *	which UTF-8 is compatible:
 *
 *	The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z' occupy
 *	consecutive code points, and '0' < 'A' < 'a'.
 *
 *----------------------------------------------------------------------
 */

int
ParseHex(
    const char *src,		/* First character to parse. */
    int numBytes,		/* Max number of byes to scan */
    int *resultPtr)	/* Points to storage provided by caller where
				 * the character resulting from the
				 * conversion is to be written. */
{
    int result = 0;
    register const char *p = src;

    while (numBytes--) {
	unsigned char digit = UCHAR(*p);

	if (!isxdigit(digit) || (result > 0x10FFF)) {
	    break;
	}

	p++;
	result <<= 4;

	if (digit >= 'a') {
	    result |= (10 + digit - 'a');
	} else if (digit >= 'A') {
	    result |= (10 + digit - 'A');
	} else {







|



















|


|
|


|





|



|







757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
    } while (numBytes && (*p == '\n') && (p++, --numBytes));
    return (p-src);
}

/*
 *----------------------------------------------------------------------
 *
 * TclParseHex --
 *
 *	Scans a hexadecimal number as a Tcl_UniChar value (e.g., for parsing
 *	\x and \u escape sequences). At most numBytes bytes are scanned.
 *
 * Results:
 *	The numeric value is stored in *resultPtr. Returns the number of bytes
 *	consumed.
 *
 * Notes:
 *	Relies on the following properties of the ASCII character set, with
 *	which UTF-8 is compatible:
 *
 *	The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z' occupy
 *	consecutive code points, and '0' < 'A' < 'a'.
 *
 *----------------------------------------------------------------------
 */

int
TclParseHex(
    const char *src,		/* First character to parse. */
    int numBytes,		/* Max number of byes to scan */
    Tcl_UniChar *resultPtr)	/* Points to storage provided by caller where
				 * the Tcl_UniChar resulting from the
				 * conversion is to be written. */
{
    Tcl_UniChar result = 0;
    register const char *p = src;

    while (numBytes--) {
	unsigned char digit = UCHAR(*p);

	if (!isxdigit(digit)) {
	    break;
	}

	++p;
	result <<= 4;

	if (digit >= 'a') {
	    result |= (10 + digit - 'a');
	} else if (digit >= 'A') {
	    result |= (10 + digit - 'A');
	} else {
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
 *
 * TclParseBackslash --
 *
 *	Scans up to numBytes bytes starting at src, consuming a backslash
 *	sequence as defined by Tcl's parsing rules.
 *
 * Results:
 *	Records at readPtr the number of bytes making up the backslash
 *	sequence. Records at dst the UTF-8 encoded equivalent of that
 *	backslash sequence. Returns the number of bytes written to dst, at
 *	most TCL_UTF_MAX. Either readPtr or dst may be NULL, if the results
 *	are not needed, but the return value is the same either way.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclParseBackslash(
    const char *src,		/* Points to the backslash character of a a
				 * backslash sequence. */
    int numBytes,		/* Max number of bytes to scan. */
    int *readPtr,		/* NULL, or points to storage where the number
				 * of bytes scanned should be written. */
    char *dst)			/* NULL, or points to buffer where the UTF-8
				 * encoding of the backslash sequence is to be
				 * written. At most TCL_UTF_MAX bytes will be
				 * written there. */
{
    register const char *p = src+1;
    Tcl_UniChar unichar = 0;
    int result;
    int count;
    char buf[TCL_UTF_MAX];

    if (numBytes == 0) {
	if (readPtr != NULL) {
	    *readPtr = 0;
	}







|
|
|
|
|


|

















|
<







819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
 *
 * TclParseBackslash --
 *
 *	Scans up to numBytes bytes starting at src, consuming a backslash
 *	sequence as defined by Tcl's parsing rules.
 *
 * Results:
 * 	Records at readPtr the number of bytes making up the backslash
 * 	sequence. Records at dst the UTF-8 encoded equivalent of that
 * 	backslash sequence. Returns the number of bytes written to dst, at
 * 	most TCL_UTF_MAX. Either readPtr or dst may be NULL, if the results
 * 	are not needed, but the return value is the same either way.
 *
 * Side effects:
 * 	None.
 *
 *----------------------------------------------------------------------
 */

int
TclParseBackslash(
    const char *src,		/* Points to the backslash character of a a
				 * backslash sequence. */
    int numBytes,		/* Max number of bytes to scan. */
    int *readPtr,		/* NULL, or points to storage where the number
				 * of bytes scanned should be written. */
    char *dst)			/* NULL, or points to buffer where the UTF-8
				 * encoding of the backslash sequence is to be
				 * written. At most TCL_UTF_MAX bytes will be
				 * written there. */
{
    register const char *p = src+1;
    Tcl_UniChar result;

    int count;
    char buf[TCL_UTF_MAX];

    if (numBytes == 0) {
	if (readPtr != NULL) {
	    *readPtr = 0;
	}
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
	count = 1;
	goto done;
    }

    count = 2;
    switch (*p) {
	/*
	 * Note: in the conversions below, use absolute values (e.g., 0xA)
	 * rather than symbolic values (e.g. \n) that get converted by the
	 * compiler. It's possible that compilers on some platforms will do
	 * the symbolic conversions differently, which could result in
	 * non-portable Tcl scripts.
	 */

    case 'a':
	result = 0x7;
	break;
    case 'b':
	result = 0x8;
	break;
    case 'f':
	result = 0xC;
	break;
    case 'n':
	result = 0xA;
	break;
    case 'r':
	result = 0xD;
	break;
    case 't':
	result = 0x9;
	break;
    case 'v':
	result = 0xB;
	break;
    case 'x':
	count += ParseHex(p+1, numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "x".
	     */

	    result = 'x';
	} else {
	    /*
	     * Keep only the last byte (2 hex digits).
	     */
	    result = (unsigned char) result;
	}
	break;
    case 'u':
	count += ParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "u".
	     */
	    result = 'u';
#if TCL_UTF_MAX > 3
	} else if (((result & 0xFC00) == 0xD800) && (count == 6)
		    && (p[5] == '\\') && (p[6] == 'u') && (numBytes >= 10)) {
	    /* If high surrogate is immediately followed by a low surrogate
	     * escape, combine them into one character. */
	    int low;
	    int count2 = ParseHex(p+7, 4, &low);
	    if ((count2 == 4) && ((low & 0xFC00) == 0xDC00)) {
		result = ((result & 0x3FF)<<10 | (low & 0x3FF)) + 0x10000;
		count += count2 + 2;
	    }
#endif
	}
	break;
#if TCL_UTF_MAX > 3
    case 'U':
	count += ParseHex(p+1, (numBytes > 9) ? 8 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "U".
	     */
	    result = 'U';
	} else if ((result | 0x7FF) == 0xDFFF) {
	    /* Upper or lower surrogate, not allowed in this syntax. */
	    result = 0xFFFD;
	}
	break;
#endif
    case '\n':
	count--;
	do {
	    p++;
	    count++;
	} while ((count < numBytes) && ((*p == ' ') || (*p == '\t')));
	result = ' ';
	break;
    case 0:
	result = '\\';
	count = 1;
	break;
    default:
	/*
	 * Check for an octal number \oo?o?
	 */

	if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) {	/* INTL: digit */
	    result = UCHAR(*p - '0');
	    p++;
	    if ((numBytes == 2) || !isdigit(UCHAR(*p))	/* INTL: digit */
		    || (UCHAR(*p) >= '8')) {
		break;
	    }
	    count = 3;
	    result = UCHAR((result << 3) + (*p - '0'));
	    p++;
	    if ((numBytes == 3) || !isdigit(UCHAR(*p))	/* INTL: digit */
		    || (UCHAR(*p) >= '8')) {
		break;
	    }
	    count = 4;
	    result = UCHAR((result << 3) + (*p - '0'));
	    break;
	}

	/*
	 * We have to convert here in case the user has put a backslash in
	 * front of a multi-byte utf-8 character. While this means nothing
	 * special, we shouldn't break up a correct utf-8 character. [Bug
	 * #217987] test subst-3.2
	 */

	if (Tcl_UtfCharComplete(p, numBytes - 1)) {
	    count = Tcl_UtfToUniChar(p, &unichar) + 1;	/* +1 for '\' */
	} else {
	    char utfBytes[TCL_UTF_MAX];

	    memcpy(utfBytes, p, (size_t) (numBytes - 1));
	    utfBytes[numBytes - 1] = '\0';
	    count = Tcl_UtfToUniChar(utfBytes, &unichar) + 1;
	}
	result = unichar;
	break;
    }

  done:
    if (readPtr != NULL) {
	*readPtr = count;
    }
    return Tcl_UniCharToUtf(result, dst);
}

/*
 *----------------------------------------------------------------------
 *
 * ParseComment --
 *
 *	Scans up to numBytes bytes starting at src, consuming a Tcl comment as
 *	defined by Tcl's parsing rules.
 *
 * Results:
 *	Records in parsePtr information about the parse. Returns the number of
 *	bytes consumed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ParseComment(
    const char *src,		/* First character to parse. */







|













|


|


|





|


|


|











|


|


<
<
<
<
<
<
<
<
<
<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<


















|






|






|











|





|

<







|











|
|


|







872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928










929


930














931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982

983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
	count = 1;
	goto done;
    }

    count = 2;
    switch (*p) {
	/*
	 * Note: in the conversions below, use absolute values (e.g., 0xa)
	 * rather than symbolic values (e.g. \n) that get converted by the
	 * compiler. It's possible that compilers on some platforms will do
	 * the symbolic conversions differently, which could result in
	 * non-portable Tcl scripts.
	 */

    case 'a':
	result = 0x7;
	break;
    case 'b':
	result = 0x8;
	break;
    case 'f':
	result = 0xc;
	break;
    case 'n':
	result = 0xa;
	break;
    case 'r':
	result = 0xd;
	break;
    case 't':
	result = 0x9;
	break;
    case 'v':
	result = 0xb;
	break;
    case 'x':
	count += TclParseHex(p+1, numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexadigits -> This is just "x".
	     */

	    result = 'x';
	} else {
	    /*
	     * Keep only the last byte (2 hex digits).
	     */
	    result = (unsigned char) result;
	}
	break;
    case 'u':
	count += TclParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexadigits -> This is just "u".
	     */
	    result = 'u';










	}


	break;














    case '\n':
	count--;
	do {
	    p++;
	    count++;
	} while ((count < numBytes) && ((*p == ' ') || (*p == '\t')));
	result = ' ';
	break;
    case 0:
	result = '\\';
	count = 1;
	break;
    default:
	/*
	 * Check for an octal number \oo?o?
	 */

	if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) {	/* INTL: digit */
	    result = (unsigned char)(*p - '0');
	    p++;
	    if ((numBytes == 2) || !isdigit(UCHAR(*p))	/* INTL: digit */
		    || (UCHAR(*p) >= '8')) {
		break;
	    }
	    count = 3;
	    result = (unsigned char)((result << 3) + (*p - '0'));
	    p++;
	    if ((numBytes == 3) || !isdigit(UCHAR(*p))	/* INTL: digit */
		    || (UCHAR(*p) >= '8')) {
		break;
	    }
	    count = 4;
	    result = (unsigned char)((result << 3) + (*p - '0'));
	    break;
	}

	/*
	 * We have to convert here in case the user has put a backslash in
	 * front of a multi-byte utf-8 character. While this means nothing
	 * special, we shouldn't break up a correct utf-8 character. [Bug
	 * #217987] test subst-3.2
	 */

	if (Tcl_UtfCharComplete(p, numBytes - 1)) {
	    count = Tcl_UtfToUniChar(p, &result) + 1;	/* +1 for '\' */
	} else {
	    char utfBytes[TCL_UTF_MAX];

	    memcpy(utfBytes, p, (size_t) (numBytes - 1));
	    utfBytes[numBytes - 1] = '\0';
	    count = Tcl_UtfToUniChar(utfBytes, &result) + 1;
	}

	break;
    }

  done:
    if (readPtr != NULL) {
	*readPtr = count;
    }
    return Tcl_UniCharToUtf((int) result, dst);
}

/*
 *----------------------------------------------------------------------
 *
 * ParseComment --
 *
 *	Scans up to numBytes bytes starting at src, consuming a Tcl comment as
 *	defined by Tcl's parsing rules.
 *
 * Results:
 * 	Records in parsePtr information about the parse. Returns the number of
 * 	bytes consumed.
 *
 * Side effects:
 * 	None.
 *
 *----------------------------------------------------------------------
 */

static int
ParseComment(
    const char *src,		/* First character to parse. */
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
		parsePtr->numTokens++;
		src++;
		numBytes--;
		continue;
	    }

	    /*
	     * This is a variable reference. Call Tcl_ParseVarName to do all
	     * the dirty work of parsing the name.
	     */

	    varToken = parsePtr->numTokens;
	    if (Tcl_ParseVarName(parsePtr->interp, src, numBytes, parsePtr,
		    1) != TCL_OK) {
		return TCL_ERROR;







|







1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
		parsePtr->numTokens++;
		src++;
		numBytes--;
		continue;
	    }

	    /*
	     * This is a variable reference.  Call Tcl_ParseVarName to do all
	     * the dirty work of parsing the name.
	     */

	    varToken = parsePtr->numTokens;
	    if (Tcl_ParseVarName(parsePtr->interp, src, numBytes, parsePtr,
		    1) != TCL_OK) {
		return TCL_ERROR;
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
		parsePtr->numTokens++;
		src++;
		numBytes--;
		continue;
	    }

	    /*
	     * Command substitution. Call Tcl_ParseCommand recursively (and
	     * repeatedly) to parse the nested command(s), then throw away the
	     * parse information.
	     */

	    src++;
	    numBytes--;
	    nestedPtr = (Tcl_Parse *)
		    TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse));
	    while (1) {
		const char *curEnd;

		if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1,
			nestedPtr) != TCL_OK) {
		    parsePtr->errorType = nestedPtr->errorType;
		    parsePtr->term = nestedPtr->term;
		    parsePtr->incomplete = nestedPtr->incomplete;
		    TclStackFree(parsePtr->interp, nestedPtr);
		    return TCL_ERROR;







|










|







1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
		parsePtr->numTokens++;
		src++;
		numBytes--;
		continue;
	    }

	    /*
	     * Command substitution.  Call Tcl_ParseCommand recursively (and
	     * repeatedly) to parse the nested command(s), then throw away the
	     * parse information.
	     */

	    src++;
	    numBytes--;
	    nestedPtr = (Tcl_Parse *)
		    TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse));
	    while (1) {
		const char *curEnd;
		
		if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1,
			nestedPtr) != TCL_OK) {
		    parsePtr->errorType = nestedPtr->errorType;
		    parsePtr->term = nestedPtr->term;
		    parsePtr->incomplete = nestedPtr->incomplete;
		    TclStackFree(parsePtr->interp, nestedPtr);
		    return TCL_ERROR;
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

void
Tcl_FreeParse(
    Tcl_Parse *parsePtr)	/* Structure that was filled in by a previous
				 * call to Tcl_ParseCommand. */
{
    if (parsePtr->tokenPtr != parsePtr->staticTokens) {
	ckfree((char *)parsePtr->tokenPtr);
	parsePtr->tokenPtr = parsePtr->staticTokens;
    }
}

/*
 *----------------------------------------------------------------------
 *







|







1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347

void
Tcl_FreeParse(
    Tcl_Parse *parsePtr)	/* Structure that was filled in by a previous
				 * call to Tcl_ParseCommand. */
{
    if (parsePtr->tokenPtr != parsePtr->staticTokens) {
	ckfree((char *) parsePtr->tokenPtr);
	parsePtr->tokenPtr = parsePtr->staticTokens;
    }
}

/*
 *----------------------------------------------------------------------
 *
1417
1418
1419
1420
1421
1422
1423



1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
				 * reinitialize it. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int varIndex;
    unsigned array;




    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }

    /*
     * Generate one token for the variable, an additional token for the name,
     * plus any number of additional tokens for the index, if there is one.
     */

    src = start;







>
>
>
|


>



<
<
<







1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402



1403
1404
1405
1406
1407
1408
1409
				 * reinitialize it. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int varIndex;
    unsigned array;

    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }




    /*
     * Generate one token for the variable, an additional token for the name,
     * plus any number of additional tokens for the index, if there is one.
     */

    src = start;
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708



1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of string enclosed in braces. The
				 * first character must be {'. */
    register int numBytes,	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to the
				 * first null character. */
    register Tcl_Parse *parsePtr,
				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the terminating '}' if the parse was
				 * successful. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int startIndex, level, length;




    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }

    src = start;
    startIndex = parsePtr->numTokens;

    TclGrowParseTokenArray(parsePtr, 1);
    tokenPtr = &parsePtr->tokenPtr[startIndex];
    tokenPtr->type = TCL_TOKEN_TEXT;







|














>
>
>
|


>



<
<
<







1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688



1689
1690
1691
1692
1693
1694
1695
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of string enclosed in braces. The
				 * first character must be {'. */
    register int numBytes,	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to the
				 * first null character. */
    register Tcl_Parse *parsePtr,
    				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the terminating '}' if the parse was
				 * successful. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int startIndex, level, length;

    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }




    src = start;
    startIndex = parsePtr->numTokens;

    TclGrowParseTokenArray(parsePtr, 1);
    tokenPtr = &parsePtr->tokenPtr[startIndex];
    tokenPtr->type = TCL_TOKEN_TEXT;
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
	    case '{':
		openBrace = 1;
		break;
	    case '\n':
		openBrace = 0;
		break;
	    case '#' :
		if (openBrace && TclIsSpaceProcM(src[-1])) {
		    Tcl_AppendResult(parsePtr->interp,
			    ": possible unbalanced brace in comment", NULL);
		    goto error;
		}
		break;
	    }
	}







|







1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
	    case '{':
		openBrace = 1;
		break;
	    case '\n':
		openBrace = 0;
		break;
	    case '#' :
		if (openBrace && TclIsSpaceProc(src[-1])) {
		    Tcl_AppendResult(parsePtr->interp,
			    ": possible unbalanced brace in comment", NULL);
		    goto error;
		}
		break;
	    }
	}
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904



1905
1906
1907

1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of the quoted string. The first
				 * character must be '"'. */
    register int numBytes,	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to the
				 * first null character. */
    register Tcl_Parse *parsePtr,
				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the quoted string's terminating close-quote
				 * if the parse succeeds. */
{



    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }

    if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, TCL_SUBST_ALL,
	    parsePtr)) {
	goto error;
    }
    if (*parsePtr->term != '"') {
	if (parsePtr->interp != NULL) {







|










>
>
>
|


>



<
<
<







1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885



1886
1887
1888
1889
1890
1891
1892
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of the quoted string. The first
				 * character must be '"'. */
    register int numBytes,	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to the
				 * first null character. */
    register Tcl_Parse *parsePtr,
    				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the quoted string's terminating close-quote
				 * if the parse succeeds. */
{
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }




    if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, TCL_SUBST_ALL,
	    parsePtr)) {
	goto error;
    }
    if (*parsePtr->term != '"') {
	if (parsePtr->interp != NULL) {
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
	    Tcl_DecrRefCount(result);
	    if (errMsg != NULL) {
		Tcl_DecrRefCount(errMsg);
	    }
	    return NULL;
	case TCL_BREAK:
	    tokensLeft = 0;		/* Halt substitution */
	    /* FALLTHRU */
	default:
	    Tcl_AppendObjToObj(result, Tcl_GetObjResult(interp));
	}

	if (tokensLeft == 0) {
	    Tcl_FreeParse(parsePtr);
	    TclStackFree(interp, parsePtr);







<







2128
2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
	    Tcl_DecrRefCount(result);
	    if (errMsg != NULL) {
		Tcl_DecrRefCount(errMsg);
	    }
	    return NULL;
	case TCL_BREAK:
	    tokensLeft = 0;		/* Halt substitution */

	default:
	    Tcl_AppendObjToObj(result, Tcl_GetObjResult(interp));
	}

	if (tokensLeft == 0) {
	    Tcl_FreeParse(parsePtr);
	    TclStackFree(interp, parsePtr);
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
 *
 *	Accepts an array of count Tcl_Token's, and creates a result value in
 *	the interp from concatenating the results of performing Tcl
 *	substitution on each Tcl_Token. Substitution is interrupted if any
 *	non-TCL_OK completion code arises.
 *
 * Results:
 *	The return value is a standard Tcl completion code. The result in
 *	interp is the substituted value, or an error message if TCL_ERROR is
 *	returned. If tokensLeftPtr is not NULL, then it points to an int where
 *	the number of tokens remaining to be processed is written.
 *
 * Side effects:
 *	Can be anything, depending on the types of substitution done.
 *
 *----------------------------------------------------------------------
 */

int
TclSubstTokens(
    Tcl_Interp *interp,		/* Interpreter in which to lookup variables,







|
|
|
|


|







2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
 *
 *	Accepts an array of count Tcl_Token's, and creates a result value in
 *	the interp from concatenating the results of performing Tcl
 *	substitution on each Tcl_Token. Substitution is interrupted if any
 *	non-TCL_OK completion code arises.
 *
 * Results:
 * 	The return value is a standard Tcl completion code. The result in
 * 	interp is the substituted value, or an error message if TCL_ERROR is
 * 	returned. If tokensLeftPtr is not NULL, then it points to an int where
 * 	the number of tokens remaining to be processed is written.
 *
 * Side effects:
 * 	Can be anything, depending on the types of substitution done.
 *
 *----------------------------------------------------------------------
 */

int
TclSubstTokens(
    Tcl_Interp *interp,		/* Interpreter in which to lookup variables,
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
			      * generating arguments for which this is true.
			      */
{
    Tcl_Obj *result;
    int code = TCL_OK;
#define NUM_STATIC_POS 20
    int isLiteral, maxNumCL, numCL, i, adjust;
    int *clPosition = NULL;
    Interp *iPtr = (Interp *) interp;
    int inFile = iPtr->evalFlags & TCL_EVAL_FILE;

    /*
     * Each pass through this loop will substitute one token, and its
     * components, if any. The only thing tricky here is that we go to some
     * effort to pass Tcl_Obj's through untouched, to avoid string copying and
     * Tcl_Obj creation if possible, to aid performance and limit shimmering.
     *
     * Further optimization opportunities might be to check for the equivalent
     * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them.
     */

    /*
     * For the handling of continuation lines in literals we first check if
     * this is actually a literal. For if not we can forego the additional
     * processing. Otherwise we pre-allocate a small table to store the
     * locations of all continuation lines we find in this literal, if any.
     * The table is extended if needed.
     */

    numCL = 0;
    maxNumCL = 0;
    isLiteral = 1;
    for (i=0 ; i < count; i++) {
	if ((tokenPtr[i].type != TCL_TOKEN_TEXT)
		&& (tokenPtr[i].type != TCL_TOKEN_BS)) {
	    isLiteral = 0;
	    break;
	}
    }

    if (isLiteral) {
	maxNumCL = NUM_STATIC_POS;
	clPosition = (int *)ckalloc(maxNumCL * sizeof(int));
    }

    adjust = 0;
    result = NULL;
    for (; count>0 && code==TCL_OK ; count--, tokenPtr++) {
	Tcl_Obj *appendObj = NULL;
	const char *append = NULL;
	int appendByteLength = 0;
	char utfCharBytes[TCL_UTF_MAX];

	switch (tokenPtr->type) {
	case TCL_TOKEN_TEXT:
	    append = tokenPtr->start;
	    appendByteLength = tokenPtr->size;
	    break;

	case TCL_TOKEN_BS:
	    appendByteLength = TclParseBackslash(tokenPtr->start,
		    tokenPtr->size, NULL, utfCharBytes);
	    append = utfCharBytes;

	    /*
	     * If the backslash sequence we found is in a literal, and
	     * represented a continuation line, we compute and store its
	     * location (as char offset to the beginning of the _result_
	     * script). We may have to extend the table of locations.
	     *
	     * Note that the continuation line information is relevant even if
	     * the word we are processing is not a literal, as it can affect
	     * nested commands. See the branch for TCL_TOKEN_COMMAND below,
	     * where the adjustment we are tracking here is taken into
	     * account. The good thing is that we do not need a table of
	     * everything, just the number of lines we have to add as
	     * correction.
	     */

	    if ((appendByteLength == 1) && (utfCharBytes[0] == ' ') &&
		(tokenPtr->start[1] == '\n')) {
		if (isLiteral) {
		    int clPos;

		    if (result == 0) {
			clPos = 0;
		    } else {
			Tcl_GetStringFromObj(result, &clPos);
		    }

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			clPosition = (int *)ckrealloc ((char*)clPosition,
						       maxNumCL*sizeof(int));
		    }
		    clPosition[numCL] = clPos;
		    numCL++;
		}
		adjust++;
	    }
	    break;

	case TCL_TOKEN_COMMAND: {
	    Interp *iPtr = (Interp *) interp;

	    iPtr->numLevels++;
	    code = TclInterpReady(interp);
	    if (code == TCL_OK) {
		/*
		 * Test cases: info-30.{6,8,9}
		 */

		int theline;

		TclAdvanceContinuations(&line, &clNextOuter,
			tokenPtr->start - outerScript);
		theline = line + adjust;
		/* TIP #280: Transfer line information to nested command */
		code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
			0, theline, clNextOuter, outerScript);
		/*
		 * Restore flag reset by nested eval for future bracketed
		 * commands and their cmdframe setup
		 */

		if (inFile) {
		    iPtr->evalFlags |= TCL_EVAL_FILE;
		}
	    }
	    iPtr->numLevels--;
	    appendObj = Tcl_GetObjResult(interp);
	    break;
	}







|
|
















|
|


|
|


|
|






|
|




















<



















<








|



|

|














<
|
|








<
|







2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318

2319
2320
2321
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2336
			      * generating arguments for which this is true.
			      */
{
    Tcl_Obj *result;
    int code = TCL_OK;
#define NUM_STATIC_POS 20
    int isLiteral, maxNumCL, numCL, i, adjust;
    int* clPosition = NULL;
    Interp* iPtr = (Interp*) interp;
    int inFile = iPtr->evalFlags & TCL_EVAL_FILE;

    /*
     * Each pass through this loop will substitute one token, and its
     * components, if any. The only thing tricky here is that we go to some
     * effort to pass Tcl_Obj's through untouched, to avoid string copying and
     * Tcl_Obj creation if possible, to aid performance and limit shimmering.
     *
     * Further optimization opportunities might be to check for the equivalent
     * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them.
     */

    /*
     * For the handling of continuation lines in literals we first check if
     * this is actually a literal. For if not we can forego the additional
     * processing. Otherwise we pre-allocate a small table to store the
     * locations of all continuation lines we find in this literal, if
     * any. The table is extended if needed.
     */

    numCL     = 0;
    maxNumCL  = 0;
    isLiteral = 1;
    for (i=0 ; i < count; i++) {
	if ((tokenPtr[i].type != TCL_TOKEN_TEXT) &&
	    (tokenPtr[i].type != TCL_TOKEN_BS)) {
	    isLiteral = 0;
	    break;
	}
    }

    if (isLiteral) {
	maxNumCL   = NUM_STATIC_POS;
	clPosition = (int*) ckalloc (maxNumCL*sizeof(int));
    }

    adjust = 0;
    result = NULL;
    for (; count>0 && code==TCL_OK ; count--, tokenPtr++) {
	Tcl_Obj *appendObj = NULL;
	const char *append = NULL;
	int appendByteLength = 0;
	char utfCharBytes[TCL_UTF_MAX];

	switch (tokenPtr->type) {
	case TCL_TOKEN_TEXT:
	    append = tokenPtr->start;
	    appendByteLength = tokenPtr->size;
	    break;

	case TCL_TOKEN_BS:
	    appendByteLength = TclParseBackslash(tokenPtr->start,
		    tokenPtr->size, NULL, utfCharBytes);
	    append = utfCharBytes;

	    /*
	     * If the backslash sequence we found is in a literal, and
	     * represented a continuation line, we compute and store its
	     * location (as char offset to the beginning of the _result_
	     * script). We may have to extend the table of locations.
	     *
	     * Note that the continuation line information is relevant even if
	     * the word we are processing is not a literal, as it can affect
	     * nested commands. See the branch for TCL_TOKEN_COMMAND below,
	     * where the adjustment we are tracking here is taken into
	     * account. The good thing is that we do not need a table of
	     * everything, just the number of lines we have to add as
	     * correction.
	     */

	    if ((appendByteLength == 1) && (utfCharBytes[0] == ' ') &&
		(tokenPtr->start[1] == '\n')) {
		if (isLiteral) {
		    int clPos;

		    if (result == 0) {
			clPos = 0;
		    } else {
			Tcl_GetStringFromObj(result, &clPos);
		    }

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			clPosition = (int*) ckrealloc ((char*)clPosition,
						       maxNumCL*sizeof(int));
		    }
		    clPosition[numCL] = clPos;
		    numCL ++;
		}
		adjust ++;
	    }
	    break;

	case TCL_TOKEN_COMMAND: {
	    Interp *iPtr = (Interp *) interp;

	    iPtr->numLevels++;
	    code = TclInterpReady(interp);
	    if (code == TCL_OK) {
		/*
		 * Test cases: info-30.{6,8,9}
		 */

		int theline;

		TclAdvanceContinuations (&line, &clNextOuter,
					 tokenPtr->start - outerScript);
		theline = line + adjust;
		/* TIP #280: Transfer line information to nested command */
		code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
			0, theline, clNextOuter, outerScript);
		/*
		 * Restore flag reset by nested eval for future bracketed
		 * commands and their cmdframe setup
		 */

	        if (inFile) {
		    iPtr->evalFlags |= TCL_EVAL_FILE;
		}
	    }
	    iPtr->numLevels--;
	    appendObj = Tcl_GetObjResult(interp);
	    break;
	}
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
	    }
	}
    }

    if (code != TCL_ERROR) {		/* Keep error message in result! */
	if (result != NULL) {
	    Tcl_SetObjResult(interp, result);

	    /*
	     * If the code found continuation lines (which implies that this
	     * word is a literal), then we store the accumulated table of
	     * locations in the thread-global data structure for the bytecode
	     * compiler to find later, assuming that the literal is a script
	     * which will be compiled.
	     */

	    if (numCL) {
		TclContinuationsEnter(result, numCL, clPosition);
	    }

	    /*
	     * Release the temp table we used to collect the locations of
	     * continuation lines, if any.
	     */

	    if (maxNumCL) {
		ckfree((char*) clPosition);
	    }
	} else {
	    Tcl_ResetResult(interp);
	}
    }
    if (tokensLeftPtr != NULL) {
	*tokensLeftPtr = count;







<


















|







2425
2426
2427
2428
2429
2430
2431

2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
	    }
	}
    }

    if (code != TCL_ERROR) {		/* Keep error message in result! */
	if (result != NULL) {
	    Tcl_SetObjResult(interp, result);

	    /*
	     * If the code found continuation lines (which implies that this
	     * word is a literal), then we store the accumulated table of
	     * locations in the thread-global data structure for the bytecode
	     * compiler to find later, assuming that the literal is a script
	     * which will be compiled.
	     */

	    if (numCL) {
		TclContinuationsEnter(result, numCL, clPosition);
	    }

	    /*
	     * Release the temp table we used to collect the locations of
	     * continuation lines, if any.
	     */

	    if (maxNumCL) {
		ckfree ((char*) clPosition);
	    }
	} else {
	    Tcl_ResetResult(interp);
	}
    }
    if (tokensLeftPtr != NULL) {
	*tokensLeftPtr = count;

Changes to generic/tclPathObj.c.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
static void		UpdateStringOfFsPath(Tcl_Obj *pathPtr);
static int		SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr);
static int		FindSplitPos(const char *path, int separator);
static int		IsSeparatorOrNull(int ch);
static Tcl_Obj *	GetExtension(Tcl_Obj *pathPtr);
static int		MakePathFromNormalized(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr);
static Tcl_Obj *	TclJoinPath(int elements, Tcl_Obj * const objv[],
			    int forceRelative);


/*
 * Define the 'path' object type, which Tcl uses to represent file paths
 * internally.
 */

static Tcl_ObjType tclFsPathType = {







<
<
<







25
26
27
28
29
30
31



32
33
34
35
36
37
38
static void		UpdateStringOfFsPath(Tcl_Obj *pathPtr);
static int		SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr);
static int		FindSplitPos(const char *path, int separator);
static int		IsSeparatorOrNull(int ch);
static Tcl_Obj *	GetExtension(Tcl_Obj *pathPtr);
static int		MakePathFromNormalized(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr);




/*
 * Define the 'path' object type, which Tcl uses to represent file paths
 * internally.
 */

static Tcl_ObjType tclFsPathType = {
820
821
822
823
824
825
826


827
828
829
830
831
832
833
834
835
836
837
838
839
840
841

842
843

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */



Tcl_Obj *
Tcl_FSJoinPath(
    Tcl_Obj *listObj,		/* Path elements to join, may have a zero
				 * reference count. */
    int elements)		/* Number of elements to use (-1 = all) */
{
    Tcl_Obj *res;
    int objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) {
	return NULL;
    }

    elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;

    Tcl_ListObjGetElements(NULL, listObj, &objc, &objv);
    res = TclJoinPath(elements, objv, 0);

    return res;
}

static Tcl_Obj *
TclJoinPath(
    int elements,		/* Number of elements to use (-1 = all) */
    Tcl_Obj * const objv[],	/* Path elements to join */
    int forceRelative)		/* If non-zero, assume all more paths are
				 * relative (e. g. simple normalization) */
{
    Tcl_Obj *res = NULL;	/* Resulting path object (container of join) */
    Tcl_Obj *elt;		/* Path part (result if returns part of path) */
    int i;
    Tcl_Filesystem *fsPtr = NULL;

    for (i = 0; i < elements; i++) {
	int driveNameLength, strEltLen, length;
	Tcl_PathType type;
	char *strElt, *ptr;
	Tcl_Obj *driveName = NULL;

	elt = objv[i];

	/*
	 * This is a special case where we can be much more efficient, where
	 * we are joining a single relative path onto an object that is
	 * already of path type. The 'TclNewFSPathObj' call below creates an
	 * object which can be normalized more efficiently. Currently we only
	 * use the special case when we have exactly two elements, but we
	 * could expand that in the future.
         *
         * Bugfix [a47641a0]. TclNewFSPathObj requires first argument
         * to be an absolute path. Added a check for that elt is absolute.
	 */

	if ((i == 0) && (elements == 2)
                && (elt->typePtr == &tclFsPathType)
		&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
                && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
            Tcl_Obj *tailObj = objv[i+1];
	    /* if forceRelative - second path is relative */
	    type = forceRelative ? TCL_PATH_RELATIVE :
		    TclGetPathType(tailObj, NULL, NULL, NULL);
	    if (type == TCL_PATH_RELATIVE) {
		const char *str;
		int len;

		str = Tcl_GetStringFromObj(tailObj, &len);
		if (len == 0) {
		    /*







>
>






|








>

|
>



|

|
|
<
<











|














|




|
<
|







817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851


852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[]);

Tcl_Obj *
Tcl_FSJoinPath(
    Tcl_Obj *listObj,		/* Path elements to join, may have a zero
				 * reference count. */
    int elements)		/* Number of elements to use (-1 = all) */
{
    Tcl_Obj *copy, *res;
    int objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) {
	return NULL;
    }

    elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;
    copy = TclListObjCopy(NULL, listObj);
    Tcl_ListObjGetElements(NULL, listObj, &objc, &objv);
    res = TclJoinPath(elements, objv);
    Tcl_DecrRefCount(copy);
    return res;
}

Tcl_Obj *
TclJoinPath(
    int elements,
    Tcl_Obj * const objv[])


{
    Tcl_Obj *res = NULL;	/* Resulting path object (container of join) */
    Tcl_Obj *elt;		/* Path part (result if returns part of path) */
    int i;
    Tcl_Filesystem *fsPtr = NULL;

    for (i = 0; i < elements; i++) {
	int driveNameLength, strEltLen, length;
	Tcl_PathType type;
	char *strElt, *ptr;
	Tcl_Obj *driveName = NULL;
	
	elt = objv[i];

	/*
	 * This is a special case where we can be much more efficient, where
	 * we are joining a single relative path onto an object that is
	 * already of path type. The 'TclNewFSPathObj' call below creates an
	 * object which can be normalized more efficiently. Currently we only
	 * use the special case when we have exactly two elements, but we
	 * could expand that in the future.
         *
         * Bugfix [a47641a0]. TclNewFSPathObj requires first argument
         * to be an absolute path. Added a check for that elt is absolute.
	 */

	if ((i == (elements-2)) && (i == 0)
                && (elt->typePtr == &tclFsPathType)
		&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
                && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
            Tcl_Obj *tailObj = objv[i+1];


	    type = TclGetPathType(tailObj, NULL, NULL, NULL);
	    if (type == TCL_PATH_RELATIVE) {
		const char *str;
		int len;

		str = Tcl_GetStringFromObj(tailObj, &len);
		if (len == 0) {
		    /*
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
			goto partReturn; /* return elt; */
		    }
		}
	    }
	}
	strElt = Tcl_GetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;
	/* if forceRelative - all paths excepting first one are relative */
	type = (forceRelative && (i > 0)) ? TCL_PATH_RELATIVE :
		TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
	if (type != TCL_PATH_RELATIVE) {
	    /*
	     * Zero out the current result.
	     */

	    if (res != NULL) {
		TclDecrRefCount(res);







<
<
|







949
950
951
952
953
954
955


956
957
958
959
960
961
962
963
			goto partReturn; /* return elt; */
		    }
		}
	    }
	}
	strElt = Tcl_GetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;


	type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
	if (type != TCL_PATH_RELATIVE) {
	    /*
	     * Zero out the current result.
	     */

	    if (res != NULL) {
		TclDecrRefCount(res);
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
                   len = 0;
               }
               break;
           default:
               count = 0;
               state = 1;
           }
           break;
       case 1: /* Scanning for next dirsep */
           switch (*p) {
           case '/':
           case '\\':
           case ':':
               state = 0;
               break;







<







1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
                   len = 0;
               }
               break;
           default:
               count = 0;
               state = 1;
           }

       case 1: /* Scanning for next dirsep */
           switch (*p) {
           case '/':
           case '\\':
           case ':':
               state = 0;
               break;
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426


2427
2428
2429
2430
2431


2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443




2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476



2477
2478

2479

2480
2481
2482
2483
2484
2485
2486

    name = Tcl_GetStringFromObj(pathPtr, &len);

    /*
     * Handle tilde substitutions, if needed.
     */

    if (len && name[0] == '~') {
	char *expandedUser;
	Tcl_DString temp;
	int split;
	char separator = '/';



	/*
	 * We have multiple cases '~/foo/bar...', '~user/foo/bar...', etc.
	 * split becomes value 1 for '~/...' as well as for '~'.
	 */
	split = FindSplitPos(name, separator);



	/*
	 * Do some tilde substitution.
	 */

	if (split == 1) {
	    /*
	     * We have just '~' (or '~/...')
	     */

	    const char *dir;
	    Tcl_DString dirString;





	    dir = TclGetEnv("HOME", &dirString);
	    if (dir == NULL) {
		if (interp) {
		    Tcl_ResetResult(interp);
		    Tcl_AppendResult(interp, "couldn't find HOME environment "
			    "variable to expand path", NULL);
		}
		return TCL_ERROR;
	    }
	    Tcl_DStringInit(&temp);
	    Tcl_JoinPath(1, &dir, &temp);
	    Tcl_DStringFree(&dirString);
	} else {
	    /*
	     * We have a user name '~user'
	     */

	    Tcl_DString userName;

	    Tcl_DStringInit(&userName);
	    Tcl_DStringAppend(&userName, name+1, split-1);
	    expandedUser = Tcl_DStringValue(&userName);

	    Tcl_DStringInit(&temp);
	    if (TclpGetUserHome(expandedUser, &temp) == NULL) {
		if (interp != NULL) {
		    Tcl_ResetResult(interp);
		    Tcl_AppendResult(interp, "user \"", expandedUser,
			    "\" doesn't exist", NULL);
		}
		Tcl_DStringFree(&userName);
		Tcl_DStringFree(&temp);



		return TCL_ERROR;
	    }

	    Tcl_DStringFree(&userName);

	}

	expandedUser = Tcl_DStringValue(&temp);
	transPtr = Tcl_NewStringObj(expandedUser, Tcl_DStringLength(&temp));

	if (split != len) {
	    /*







|





>
>
|
|
<
|
|
>
>





|

|




>
>
>
>


















<
<
<
<
<
<

|


|


<

>
>
>


>
|
>







2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463






2464
2465
2466
2467
2468
2469
2470

2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486

    name = Tcl_GetStringFromObj(pathPtr, &len);

    /*
     * Handle tilde substitutions, if needed.
     */

    if (name[0] == '~') {
	char *expandedUser;
	Tcl_DString temp;
	int split;
	char separator = '/';

	split = FindSplitPos(name, separator);
	if (split != len) {
	    /*
	     * We have multiple pieces '~user/foo/bar...'

	     */

	    name[split] = '\0';
	}

	/*
	 * Do some tilde substitution.
	 */

	if (name[1] == '\0') {
	    /*
	     * We have just '~'
	     */

	    const char *dir;
	    Tcl_DString dirString;

	    if (split != len) {
		name[split] = separator;
	    }

	    dir = TclGetEnv("HOME", &dirString);
	    if (dir == NULL) {
		if (interp) {
		    Tcl_ResetResult(interp);
		    Tcl_AppendResult(interp, "couldn't find HOME environment "
			    "variable to expand path", NULL);
		}
		return TCL_ERROR;
	    }
	    Tcl_DStringInit(&temp);
	    Tcl_JoinPath(1, &dir, &temp);
	    Tcl_DStringFree(&dirString);
	} else {
	    /*
	     * We have a user name '~user'
	     */







	    Tcl_DStringInit(&temp);
	    if (TclpGetUserHome(name+1, &temp) == NULL) {
		if (interp != NULL) {
		    Tcl_ResetResult(interp);
		    Tcl_AppendResult(interp, "user \"", name+1,
			    "\" doesn't exist", NULL);
		}

		Tcl_DStringFree(&temp);
		if (split != len) {
		    name[split] = separator;
		}
		return TCL_ERROR;
	    }
	    if (split != len) {
		name[split] = separator;
	    }
	}

	expandedUser = Tcl_DStringValue(&temp);
	transPtr = Tcl_NewStringObj(expandedUser, Tcl_DStringLength(&temp));

	if (split != len) {
	    /*
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
		}
		TclDecrRefCount(parts);
	    } else {
		Tcl_Obj *pair[2];

		pair[0] = transPtr;
		pair[1] = Tcl_NewStringObj(name+split+1, -1);
		transPtr = TclJoinPath(2, pair, 1);
		if (transPtr != pair[0]) {
		    TclDecrRefCount(pair[0]);
		}
		if (transPtr != pair[1]) {
		    TclDecrRefCount(pair[1]);
		}
	    }
	}
	Tcl_DStringFree(&temp);
    } else {
	transPtr = TclJoinPath(1, &pathPtr, 1);
    }

    /*
     * Now we have a translated filename in 'transPtr'. This will have forward
     * slashes on Windows, and will not contain any ~user sequences.
     */








|
<
|
<
<
|
<




|







2510
2511
2512
2513
2514
2515
2516
2517

2518


2519

2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
		}
		TclDecrRefCount(parts);
	    } else {
		Tcl_Obj *pair[2];

		pair[0] = transPtr;
		pair[1] = Tcl_NewStringObj(name+split+1, -1);
		transPtr = TclJoinPath(2, pair);

		TclDecrRefCount(pair[0]);


		TclDecrRefCount(pair[1]);

	    }
	}
	Tcl_DStringFree(&temp);
    } else {
	transPtr = TclJoinPath(1, &pathPtr);
    }

    /*
     * Now we have a translated filename in 'transPtr'. This will have forward
     * slashes on Windows, and will not contain any ~user sequences.
     */

Changes to generic/tclPipe.c.

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
    TclFile *inPipePtr,		/* If non-NULL, input to the pipeline comes
				 * from a pipe (unless overridden by
				 * redirection in the command). The file id
				 * with which to write to this pipe is stored
				 * at *inPipePtr. NULL means command specified
				 * its own input source. */
    TclFile *outPipePtr,	/* If non-NULL, output to the pipeline goes to
				 * a pipe, unless overridden by redirection in
				 * the command. The file id with which to read
				 * frome this pipe is stored at *outPipePtr.
				 * NULL means command specified its own output
				 * sink. */
    TclFile *errFilePtr)	/* If non-NULL, all stderr output from the
				 * pipeline will go to a temporary file
				 * created here, and a descriptor to read the







|







438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
    TclFile *inPipePtr,		/* If non-NULL, input to the pipeline comes
				 * from a pipe (unless overridden by
				 * redirection in the command). The file id
				 * with which to write to this pipe is stored
				 * at *inPipePtr. NULL means command specified
				 * its own input source. */
    TclFile *outPipePtr,	/* If non-NULL, output to the pipeline goes to
				 * a pipe, unless overriden by redirection in
				 * the command. The file id with which to read
				 * frome this pipe is stored at *outPipePtr.
				 * NULL means command specified its own output
				 * sink. */
    TclFile *errFilePtr)	/* If non-NULL, all stderr output from the
				 * pipeline will go to a temporary file
				 * created here, and a descriptor to read the

Changes to generic/tclPlatDecls.h.

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
#endif
#ifndef Tcl_WinTCharToUtf_TCL_DECLARED
#define Tcl_WinTCharToUtf_TCL_DECLARED
/* 1 */
EXTERN char *		Tcl_WinTCharToUtf(CONST TCHAR *str, int len,
				Tcl_DString *dsPtr);
#endif
/* Slot 2 is reserved */
#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 3 */
EXTERN void		TclUnusedStubEntry(void);
#endif
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#ifndef Tcl_MacOSXOpenBundleResources_TCL_DECLARED
#define Tcl_MacOSXOpenBundleResources_TCL_DECLARED
/* 0 */
EXTERN int		Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
				CONST char *bundleName, int hasResourceFile,
				int maxPathLen, char *libraryPath);
#endif
#ifndef Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
#define Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, CONST char *bundleName,
				CONST char *bundleVersion,
				int hasResourceFile, int maxPathLen,
				char *libraryPath);
#endif
#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 2 */
EXTERN void		TclUnusedStubEntry(void);
#endif
#endif /* MACOSX */

typedef struct TclPlatStubs {
    int magic;
    struct TclPlatStubHooks *hooks;

#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
    TCHAR * (*tcl_WinUtfToTChar) (CONST char *str, int len, Tcl_DString *dsPtr); /* 0 */
    char * (*tcl_WinTCharToUtf) (CONST TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
    VOID *reserved2;
    void (*tclUnusedStubEntry) (void); /* 3 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, CONST char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, CONST char *bundleName, CONST char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */
    void (*tclUnusedStubEntry) (void); /* 2 */
#endif /* MACOSX */
} TclPlatStubs;

extern TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}







<
<
<
<
<
<


















<
<
<
<
<









<
<




<







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
#endif
#ifndef Tcl_WinTCharToUtf_TCL_DECLARED
#define Tcl_WinTCharToUtf_TCL_DECLARED
/* 1 */
EXTERN char *		Tcl_WinTCharToUtf(CONST TCHAR *str, int len,
				Tcl_DString *dsPtr);
#endif






#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#ifndef Tcl_MacOSXOpenBundleResources_TCL_DECLARED
#define Tcl_MacOSXOpenBundleResources_TCL_DECLARED
/* 0 */
EXTERN int		Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
				CONST char *bundleName, int hasResourceFile,
				int maxPathLen, char *libraryPath);
#endif
#ifndef Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
#define Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, CONST char *bundleName,
				CONST char *bundleVersion,
				int hasResourceFile, int maxPathLen,
				char *libraryPath);
#endif





#endif /* MACOSX */

typedef struct TclPlatStubs {
    int magic;
    struct TclPlatStubHooks *hooks;

#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
    TCHAR * (*tcl_WinUtfToTChar) (CONST char *str, int len, Tcl_DString *dsPtr); /* 0 */
    char * (*tcl_WinTCharToUtf) (CONST TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */


#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, CONST char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, CONST char *bundleName, CONST char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */

#endif /* MACOSX */
} TclPlatStubs;

extern TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#define Tcl_WinUtfToTChar \
	(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#endif
#ifndef Tcl_WinTCharToUtf
#define Tcl_WinTCharToUtf \
	(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
#endif
/* Slot 2 is reserved */
#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclPlatStubsPtr->tclUnusedStubEntry) /* 3 */
#endif
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#ifndef Tcl_MacOSXOpenBundleResources
#define Tcl_MacOSXOpenBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */
#endif
#ifndef Tcl_MacOSXOpenVersionedBundleResources
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#endif
#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclPlatStubsPtr->tclUnusedStubEntry) /* 2 */
#endif
#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLPLATDECLS */









<
<
<
<
<










<
<
<
<












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
#define Tcl_WinUtfToTChar \
	(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#endif
#ifndef Tcl_WinTCharToUtf
#define Tcl_WinTCharToUtf \
	(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
#endif





#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#ifndef Tcl_MacOSXOpenBundleResources
#define Tcl_MacOSXOpenBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */
#endif
#ifndef Tcl_MacOSXOpenVersionedBundleResources
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#endif




#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLPLATDECLS */


Changes to generic/tclPort.h.

35
36
37
38
39
40
41
42
43
44
45
46
#         define LLONG_MIN ((Tcl_WideInt)(Tcl_LongAsWide(1)<<63))
#      endif
#   endif
/* Assume that if LLONG_MIN is undefined, then so is LLONG_MAX */
#   define LLONG_MAX (~LLONG_MIN)
#endif

#define UWIDE_MAX ((Tcl_WideUInt)-1)
#define WIDE_MAX ((Tcl_WideInt)(UWIDE_MAX >> 1))
#define WIDE_MIN ((Tcl_WideInt)((Tcl_WideUInt)WIDE_MAX+1))

#endif /* _TCLPORT */







<
<
<


35
36
37
38
39
40
41



42
43
#         define LLONG_MIN ((Tcl_WideInt)(Tcl_LongAsWide(1)<<63))
#      endif
#   endif
/* Assume that if LLONG_MIN is undefined, then so is LLONG_MAX */
#   define LLONG_MAX (~LLONG_MIN)
#endif





#endif /* _TCLPORT */

Changes to generic/tclProc.c.

709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
    /*
     * Parse string to figure out which level number to go to.
     */

    result = 1;
    curLevel = iPtr->varFramePtr->level;
    if (*name== '#') {
	if (Tcl_GetInt(NULL, name+1, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}
    } else if (isdigit(UCHAR(*name))) { /* INTL: digit */
	if (Tcl_GetInt(NULL, name, &level) != TCL_OK) {
	    goto levelError;
	}
	level = curLevel - level;
    } else {
	/*
	 * (historical, TODO) If name does not contain a level (#0 or 1),
	 * TclGetFrame and Tcl_UpVar2 uses current level - 1
	 */
	level = curLevel - 1;
	result = 0;
	name = "1"; /* be more consistent with TclObjGetFrame (error at top - 1) */
    }

    /*
     * Figure out which frame to use, and return it to the caller.
     */

    for (framePtr = iPtr->varFramePtr; framePtr != NULL;







|



|




<
<
<
<


<







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724




725
726

727
728
729
730
731
732
733
    /*
     * Parse string to figure out which level number to go to.
     */

    result = 1;
    curLevel = iPtr->varFramePtr->level;
    if (*name== '#') {
	if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}
    } else if (isdigit(UCHAR(*name))) { /* INTL: digit */
	if (Tcl_GetInt(interp, name, &level) != TCL_OK) {
	    goto levelError;
	}
	level = curLevel - level;
    } else {




	level = curLevel - 1;
	result = 0;

    }

    /*
     * Figure out which frame to use, and return it to the caller.
     */

    for (framePtr = iPtr->varFramePtr; framePtr != NULL;
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
#endif
	    ) {
	if (TclGetIntFromObj(NULL, objPtr, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}
	level = curLevel - level;
    } else if (*name == '#') {
	if (Tcl_GetInt(NULL, name+1, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}

	/*
	 * Cache for future reference.
	 *
	 * TODO: Use the new ptrAndLongRep intrep







|







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
#endif
	    ) {
	if (TclGetIntFromObj(NULL, objPtr, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}
	level = curLevel - level;
    } else if (*name == '#') {
	if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
	    goto levelError;
	}

	/*
	 * Cache for future reference.
	 *
	 * TODO: Use the new ptrAndLongRep intrep
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
    } else {
	/*
	 * Don't cache as the object *isn't* a level reference.
	 */

	level = curLevel - 1;
	result = 0;
	name = "1";
    }

    /*
     * Figure out which frame to use, and return it to the caller.
     */

    for (framePtr = iPtr->varFramePtr; framePtr != NULL;







<







845
846
847
848
849
850
851

852
853
854
855
856
857
858
    } else {
	/*
	 * Don't cache as the object *isn't* a level reference.
	 */

	level = curLevel - 1;
	result = 0;

    }

    /*
     * Figure out which frame to use, and return it to the caller.
     */

    for (framePtr = iPtr->varFramePtr; framePtr != NULL;
1804
1805
1806
1807
1808
1809
1810
1811


1812
1813
1814
1815
1816
1817
1818

	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "invoked \"",
		((result == TCL_BREAK) ? "break" : "continue"),
		"\" outside of a loop", NULL);
	result = TCL_ERROR;

	/* FALLTHRU */



    case TCL_ERROR:
	/*
	 * Now it _must_ be an error, so we need to log it as such. This means
	 * filling out the error trace. Luckily, we just hand this off to the
	 * function handed to us as an argument.
	 */







|
>
>







1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814

	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "invoked \"",
		((result == TCL_BREAK) ? "break" : "continue"),
		"\" outside of a loop", NULL);
	result = TCL_ERROR;

	/*
	 * Fall through to the TCL_ERROR handling code.
	 */

    case TCL_ERROR:
	/*
	 * Now it _must_ be an error, so we need to log it as such. This means
	 * filling out the error trace. Luckily, we just hand this off to the
	 * function handed to us as an argument.
	 */

Changes to generic/tclResult.c.

700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
    CONST char *element)	/* String to convert to list element and add
				 * to result. */
{
    Interp *iPtr = (Interp *) interp;
    char *dst;
    int size;
    int flags;
    int quoteHash = 1;

    /*
     * If the string result is empty, move the object result to the string
     * result, then reset the object result.
     */

    (void) Tcl_GetStringResult(interp);







<







700
701
702
703
704
705
706

707
708
709
710
711
712
713
    CONST char *element)	/* String to convert to list element and add
				 * to result. */
{
    Interp *iPtr = (Interp *) interp;
    char *dst;
    int size;
    int flags;


    /*
     * If the string result is empty, move the object result to the string
     * result, then reset the object result.
     */

    (void) Tcl_GetStringResult(interp);
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
	dst++;

	/*
	 * If we need a space to separate this element from preceding stuff,
	 * then this element will not lead a list, and need not have it's
	 * leading '#' quoted.
	 */
	quoteHash = 0;
    } else {
	while ((--dst >= iPtr->appendResult) && TclIsSpaceProcM(*dst)) {
	}
	quoteHash = !TclNeedSpace(iPtr->appendResult, dst+1);
    }
    dst = iPtr->appendResult + iPtr->appendUsed;
    if (!quoteHash) {
	flags |= TCL_DONT_QUOTE_HASH;
    }

    iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * SetupAppendBuffer --







<
<
<
|
<
<
<
<


<







736
737
738
739
740
741
742



743




744
745

746
747
748
749
750
751
752
	dst++;

	/*
	 * If we need a space to separate this element from preceding stuff,
	 * then this element will not lead a list, and need not have it's
	 * leading '#' quoted.
	 */








	flags |= TCL_DONT_QUOTE_HASH;
    }

    iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * SetupAppendBuffer --

Changes to generic/tclScan.c.

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385


386
387
388
389
390
391
392
	case 'l':
	    if (*format == 'l') {
		flags |= SCAN_BIG;
		format += 1;
		format += Tcl_UtfToUniChar(format, &ch);
		break;
	    }
	    /* FALLTHRU */
	case 'L':
	    flags |= SCAN_LONGER;
	    /* FALLTHRU */
	case 'h':
	    format += Tcl_UtfToUniChar(format, &ch);
	}

	if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
	    goto badIndex;
	}

	/*
	 * Handle the various field types.
	 */

	switch (ch) {
	case 'c':
	    if (flags & SCAN_WIDTH) {
		Tcl_SetResult(interp,
			"field width may not be specified in %c conversion",
			TCL_STATIC);
		goto error;
	    }
	    /* FALLTHRU */


	case 'n':
	case 's':
	    if (flags & (SCAN_LONGER|SCAN_BIG)) {
	    invalidFieldSize:
		buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
		Tcl_AppendResult(interp,
			"field size modifier may not be specified in %", buf,







<


<




















|
>
>







354
355
356
357
358
359
360

361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
	case 'l':
	    if (*format == 'l') {
		flags |= SCAN_BIG;
		format += 1;
		format += Tcl_UtfToUniChar(format, &ch);
		break;
	    }

	case 'L':
	    flags |= SCAN_LONGER;

	case 'h':
	    format += Tcl_UtfToUniChar(format, &ch);
	}

	if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
	    goto badIndex;
	}

	/*
	 * Handle the various field types.
	 */

	switch (ch) {
	case 'c':
	    if (flags & SCAN_WIDTH) {
		Tcl_SetResult(interp,
			"field width may not be specified in %c conversion",
			TCL_STATIC);
		goto error;
	    }
	    /*
	     * Fall through!
	     */
	case 'n':
	case 's':
	    if (flags & (SCAN_LONGER|SCAN_BIG)) {
	    invalidFieldSize:
		buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
		Tcl_AppendResult(interp,
			"field size modifier may not be specified in %", buf,
690
691
692
693
694
695
696
697
698
699
700


701
702
703
704
705
706
707
	case 'l':
	    if (*format == 'l') {
		flags |= SCAN_BIG;
		format += 1;
		format += Tcl_UtfToUniChar(format, &ch);
		break;
	    }
	    /* FALLTHRU */
	case 'L':
	    flags |= SCAN_LONGER;
	    /* FALLTHRU */


	case 'h':
	    format += Tcl_UtfToUniChar(format, &ch);
	}

	/*
	 * Handle the various field types.
	 */







<


|
>
>







690
691
692
693
694
695
696

697
698
699
700
701
702
703
704
705
706
707
708
	case 'l':
	    if (*format == 'l') {
		flags |= SCAN_BIG;
		format += 1;
		format += Tcl_UtfToUniChar(format, &ch);
		break;
	    }

	case 'L':
	    flags |= SCAN_LONGER;
	    /*
	     * Fall through so we skip to the next character.
	     */
	case 'h':
	    format += Tcl_UtfToUniChar(format, &ch);
	}

	/*
	 * Handle the various field types.
	 */

Changes to generic/tclStrToD.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147

148
149
150

151
152
153
154
155

156

157

158
159
160

161
162
163
164
165
166
167
168
169
170
171
/*


 * tclStrToD.c --
 *
 *	This file contains a collection of procedures for managing conversions
 *	to/from floating-point in Tcl. They include TclParseNumber, which
 *	parses numbers from strings; TclDoubleDigits, which formats numbers
 *	into strings of digits, and procedures for interconversion among
 *	'double' and 'mp_int' types.
 *
 * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.

 */

#include "tclInt.h"
#include "tommath.h"
#include <float.h>
#include <math.h>

#ifdef _WIN32
#define copysign _copysign
#endif

/*
 * Define KILL_OCTAL to suppress interpretation of numbers with leading zero
 * as octal. (Ceterum censeo: numeros octonarios delendos esse.)
 */

#undef	KILL_OCTAL

/*
 * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754
 * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be
 * uniquely determined by radix and by the widths of significand and exponent.
 */

#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
#   define IEEE_FLOATING_POINT
#endif

/*
 * Rounding controls. (Thanks a lot, Intel!)
 */

#ifdef __i386
/*
 * gcc on x86 needs access to rounding controls, because of a questionable
 * feature where it retains intermediate results as IEEE 'long double' values
 * somewhat unpredictably. It is tempting to include fpu_control.h, but that
 * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms
 * and ix86-isms are factored out here.
 */

#if defined(__GNUC__)
typedef unsigned int	fpu_control_t __attribute__ ((__mode__ (__HI__)));

#define _FPU_GETCW(cw)	__asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
#define _FPU_SETCW(cw)	__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
#   define FPU_IEEE_ROUNDING	0x027F
#   define ADJUST_FPU_CONTROL_WORD
#define TCL_IEEE_DOUBLE_ROUNDING \
    fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING;	\
    fpu_control_t oldRoundingMode;			\
    _FPU_GETCW(oldRoundingMode);			\
    _FPU_SETCW(roundTo53Bits)
#define TCL_DEFAULT_DOUBLE_ROUNDING \
    _FPU_SETCW(oldRoundingMode)

/*
 * Sun ProC needs sunmath for rounding control on x86 like gcc above.
 */
#elif defined(__sun)
#include <sunmath.h>
#define TCL_IEEE_DOUBLE_ROUNDING \
    ieee_flags("set","precision","double",NULL)
#define TCL_DEFAULT_DOUBLE_ROUNDING \
    ieee_flags("clear","precision",NULL,NULL)

/*
 * Other platforms are assumed to always operate in full IEEE mode, so we make
 * the macros to go in and out of that mode do nothing.

 */

#else /* !__GNUC__ && !__sun */
#define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#endif
#else /* !__i386 */
#define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#endif

/*
 * MIPS floating-point units need special settings in control registers to use
 * gradual underflow as we expect.  This fix is for the MIPSpro compiler.

 */

#if defined(__sgi) && defined(_COMPILER_VERSION)
#include <sys/fpu.h>
#endif

/*
 * HP's PA_RISC architecture uses 7ff4000000000000 to represent a quiet NaN.
 * Everyone else uses 7ff8000000000000. (Why, HP, why?)
 */

#ifdef __hppa
#   define NAN_START	0x7FF4
#   define NAN_MASK	(((Tcl_WideUInt) 1) << 50)
#else
#   define NAN_START	0x7FF8
#   define NAN_MASK	(((Tcl_WideUInt) 1) << 51)
#endif

/*
 * Constants used by this file (most of which are only ever calculated at
 * runtime).
 */

/* Magic constants */

#define LOG10_2 0.3010299956639812
#define TWO_OVER_3LOG10 0.28952965460216784
#define LOG10_3HALVES_PLUS_FUDGE 0.1760912590558

/*
 * Definitions of the parts of an IEEE754-format floating point number.
 */

#define SIGN_BIT 	0x80000000
				/* Mask for the sign bit in the first word of
				 * a double. */
#define EXP_MASK	0x7FF00000
				/* Mask for the exponent field in the first
				 * word of a double. */

#define EXP_SHIFT	20	/* Shift count to make the exponent an
				 * integer. */
#define HIDDEN_BIT	(((Tcl_WideUInt) 0x00100000) << 32)
				/* Hidden 1 bit for the significand. */
#define HI_ORDER_SIG_MASK 0x000FFFFF
				/* Mask for the high-order part of the
				 * significand in the first word of a
				 * double. */
#define SIG_MASK	(((Tcl_WideUInt) HI_ORDER_SIG_MASK << 32) \
			| 0xFFFFFFFF)
				/* Mask for the 52-bit significand. */

#define FP_PRECISION	53	/* Number of bits of significand plus the
				 * hidden bit. */
#define EXPONENT_BIAS	0x3FF	/* Bias of the exponent 0. */


/*
 * Derived quantities.
 */


#define TEN_PMAX	22	/* floor(FP_PRECISION*log(2)/log(5)) */

#define QUICK_MAX	14	/* floor((FP_PRECISION-1)*log(2)/log(10))-1 */

#define BLETCH		0x10	/* Highest power of two that is greater than
				 * DBL_MAX_10_EXP, divided by 16. */
#define DIGIT_GROUP	8	/* floor(MP_DIGIT_BIT*log(2)/log(10)) */


/*
 * Union used to dismantle floating point numbers.
 */

typedef union Double {
    struct {
#ifdef WORDS_BIGENDIAN
	int word0;
	int word1;
#else

>
>












>




<


<
<
<
<


















<
<
<
<
<







|
|
<
|
|
|

<
<
<
<
<
<
|

<
|
<
<
<
<
<
<
<
|
<
<
<
>

|
|
<
<

<
<
<
<


|
|
>

<



<






|
|

|
|













<
|
<

|
|
|
|
|
|
>
|
|
|
|
|


|
|
|

>
|
|
|
>

<
|
<

>
|
>
|
>
|
|
|
>

<
|
<







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
120
121

122

123
124
125
126
127
128
129
130
131
132
133

134

135
136
137
138
139
140
141
/*
 *----------------------------------------------------------------------
 *
 * tclStrToD.c --
 *
 *	This file contains a collection of procedures for managing conversions
 *	to/from floating-point in Tcl. They include TclParseNumber, which
 *	parses numbers from strings; TclDoubleDigits, which formats numbers
 *	into strings of digits, and procedures for interconversion among
 *	'double' and 'mp_int' types.
 *
 * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *----------------------------------------------------------------------
 */

#include "tclInt.h"
#include "tommath.h"

#include <math.h>





/*
 * Define KILL_OCTAL to suppress interpretation of numbers with leading zero
 * as octal. (Ceterum censeo: numeros octonarios delendos esse.)
 */

#undef	KILL_OCTAL

/*
 * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754
 * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be
 * uniquely determined by radix and by the widths of significand and exponent.
 */

#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
#   define IEEE_FLOATING_POINT
#endif

/*





 * gcc on x86 needs access to rounding controls, because of a questionable
 * feature where it retains intermediate results as IEEE 'long double' values
 * somewhat unpredictably. It is tempting to include fpu_control.h, but that
 * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms
 * and ix86-isms are factored out here.
 */

#if defined(__GNUC__) && defined(__i386)
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));

#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
#   define FPU_IEEE_ROUNDING	0x027f
#   define ADJUST_FPU_CONTROL_WORD






#endif


/* Sun ProC needs sunmath for rounding control on x86 like gcc above.







 *



 *
 */
#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
#include <sunmath.h>


#endif





/*
 * MIPS floating-point units need special settings in control registers
 * to use gradual underflow as we expect.  This fix is for the MIPSpro
 * compiler.
 */

#if defined(__sgi) && defined(_COMPILER_VERSION)
#include <sys/fpu.h>
#endif

/*
 * HP's PA_RISC architecture uses 7ff4000000000000 to represent a quiet NaN.
 * Everyone else uses 7ff8000000000000. (Why, HP, why?)
 */

#ifdef __hppa
#   define NAN_START 0x7ff4
#   define NAN_MASK (((Tcl_WideUInt) 1) << 50)
#else
#   define NAN_START 0x7ff8
#   define NAN_MASK (((Tcl_WideUInt) 1) << 51)
#endif

/*
 * Constants used by this file (most of which are only ever calculated at
 * runtime).
 */

/* Magic constants */

#define LOG10_2 0.3010299956639812
#define TWO_OVER_3LOG10 0.28952965460216784
#define LOG10_3HALVES_PLUS_FUDGE 0.1760912590558


/* Definitions of the parts of an IEEE754-format floating point number */


#define SIGN_BIT 		0x80000000
				/* Mask for the sign bit in the first
				 * word of a double */
#define EXP_MASK	     	0x7ff00000
				/* Mask for the exponent field in the
				 * first word of a double */
#define EXP_SHIFT		20
				/* Shift count to make the exponent an
				 * integer */
#define HIDDEN_BIT		(((Tcl_WideUInt) 0x00100000) << 32)
				/* Hidden 1 bit for the significand */
#define HI_ORDER_SIG_MASK	0x000fffff
				/* Mask for the high-order part of the
				 * significand in the first word of a
				 * double */
#define SIG_MASK		(((Tcl_WideUInt) HI_ORDER_SIG_MASK << 32) \
				 | 0xffffffff)
				/* Mask for the 52-bit significand. */
#define FP_PRECISION		53
				/* Number of bits of significand plus the
				 * hidden bit */
#define EXPONENT_BIAS		0x3ff
				/* Bias of the exponent 0 */


/* Derived quantities */


#define TEN_PMAX		22
				/* floor(FP_PRECISION*log(2)/log(5)) */
#define QUICK_MAX		14
				/* floor((FP_PRECISION-1)*log(2)/log(10)) - 1 */
#define BLETCH			0x10
				/* Highest power of two that is greater than
				 * DBL_MAX_10_EXP, divided by 16 */
#define DIGIT_GROUP		8
				/* floor(DIGIT_BIT*log(2)/log(10)) */


/* Union used to dismantle floating point numbers. */


typedef union Double {
    struct {
#ifdef WORDS_BIGENDIAN
	int word0;
	int word1;
#else
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
				 * represented exactly in a 'double'. */
static int log10_DIGIT_MAX;	/* The number of decimal digits that fit in an
				 * mp_digit. */
static int log2FLT_RADIX;	/* Logarithm of the floating point radix. */
static int mantBits;		/* Number of bits in a double's significand */
static mp_int pow5[9];		/* Table of powers of 5**(2**n), up to
				 * 5**256 */
static double tiny = 0.0;	/* The smallest representable double. */
static int maxDigits;		/* The maximum number of digits to the left of
				 * the decimal point of a double. */
static int minDigits;		/* The maximum number of digits to the right
				 * of the decimal point in a double. */
static const double pow_10_2_n[] = {	/* Inexact higher powers of ten. */
    1.0,
    100.0,







|







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
				 * represented exactly in a 'double'. */
static int log10_DIGIT_MAX;	/* The number of decimal digits that fit in an
				 * mp_digit. */
static int log2FLT_RADIX;	/* Logarithm of the floating point radix. */
static int mantBits;		/* Number of bits in a double's significand */
static mp_int pow5[9];		/* Table of powers of 5**(2**n), up to
				 * 5**256 */
static double tiny = 0.0;		/* The smallest representable double */
static int maxDigits;		/* The maximum number of digits to the left of
				 * the decimal point of a double. */
static int minDigits;		/* The maximum number of digits to the right
				 * of the decimal point in a double. */
static const double pow_10_2_n[] = {	/* Inexact higher powers of ten. */
    1.0,
    100.0,
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
};

static int n770_fp;		/* Flag is 1 on Nokia N770 floating point.
				 * Nokia's floating point has the words
				 * reversed: if big-endian is 7654 3210,
				 * and little-endian is       0123 4567,
				 * then Nokia's FP is         4567 0123;
				 * little-endian within the 32-bit words but
				 * big-endian between them. */

/*
 * Table of powers of 5 that are small enough to fit in an mp_digit.
 */

static const mp_digit dpow5[13] = {
               1,              5,             25,            125,
             625,           3125,          15625,          78125,
          390625,        1953125,        9765625,       48828125,
       244140625
};

/*
 * Table of powers: pow5_13[n] = 5**(13*2**(n+1))
 */

static mp_int pow5_13[5];	/* Table of powers: 5**13, 5**26, 5**52,
				 * 5**104, 5**208 */
static const double tens[] = {
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
    1e20, 1e21, 1e22
};







|
|

<
|
<








<
|
<
<







180
181
182
183
184
185
186
187
188
189

190

191
192
193
194
195
196
197
198

199


200
201
202
203
204
205
206
};

static int n770_fp;		/* Flag is 1 on Nokia N770 floating point.
				 * Nokia's floating point has the words
				 * reversed: if big-endian is 7654 3210,
				 * and little-endian is       0123 4567,
				 * then Nokia's FP is         4567 0123;
				 * little-endian within the 32-bit words
				 * but big-endian between them. */


/* Table of powers of 5 that are small enough to fit in an mp_digit. */


static const mp_digit dpow5[13] = {
               1,              5,             25,            125,
             625,           3125,          15625,          78125,
          390625,        1953125,        9765625,       48828125,
       244140625
};


/* Table of powers: pow5_13[n] = 5**(13*2**(n+1)) */


static mp_int pow5_13[5];	/* Table of powers: 5**13, 5**26, 5**52,
				 * 5**104, 5**208 */
static const double tens[] = {
    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
    1e20, 1e21, 1e22
};
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * Static functions defined in this file.
 */

static int		AccumulateDecimalDigit(unsigned, int,
			    Tcl_WideUInt *, mp_int *, int);
static double		MakeHighPrecisionDouble(int signum,
			    mp_int *significand, int nSigDigs, long exponent);
static double		MakeLowPrecisionDouble(int signum,
			    Tcl_WideUInt significand, int nSigDigs,
			    long exponent);
static double		MakeNaN(int signum, Tcl_WideUInt tag);
static double		RefineApproximation(double approx,
			    mp_int *exactSignificand, int exponent);
static void		MulPow5(mp_int *, unsigned, mp_int *);
static int 		NormalizeRightward(Tcl_WideUInt *);
static int		RequiredPrecision(Tcl_WideUInt);
static void		DoubleToExpAndSig(double, Tcl_WideUInt *, int *,
			    int *);
static void		TakeAbsoluteValue(Double *, int *);
static char *		FormatInfAndNaN(Double *, int *, char **);
static char *		FormatZero(int *, char **);
static int		ApproximateLog10(Tcl_WideUInt, int, int);
static int		BetterLog10(double, int, int *);
static void		ComputeScale(int, int, int *, int *, int *, int *);
static void		SetPrecisionLimits(int, int, int *, int *, int *,
			    int *);
static char *		BumpUp(char *, char *, int *);
static int		AdjustRange(double *, int);
static char *		ShorteningQuickFormat(double, int, int, double,
			    char *, int *);
static char *		StrictQuickFormat(double, int, int, double,
			    char *, int *);
static char *		QuickConversion(double, int, int, int, int, int, int,
			    int *, char **);
static void		CastOutPowersOf2(int *, int *, int *);
static char *		ShorteningInt64Conversion(Double *, int, Tcl_WideUInt,
			    int, int, int, int, int, int, int, int, int,
			    int, int, int *, char **);
static char *		StrictInt64Conversion(Double *, int, Tcl_WideUInt,
			    int, int, int, int, int, int,
			    int, int, int *, char **);
static int		ShouldBankerRoundUpPowD(mp_int *, int, int);
static int		ShouldBankerRoundUpToNextPowD(mp_int *, mp_int *,
			    int, int, int, mp_int *);
static char *		ShorteningBignumConversionPowD(Double *dPtr,
			    int convType, Tcl_WideUInt bw, int b2, int b5,
			    int m2plus, int m2minus, int m5,
			    int sd, int k, int len,
			    int ilim, int ilim1, int *decpt,
			    char **endPtr);
static char *		StrictBignumConversionPowD(Double *dPtr, int convType,
			    Tcl_WideUInt bw, int b2, int b5,
			    int sd, int k, int len,
			    int ilim, int ilim1, int *decpt,
			    char **endPtr);
static int		ShouldBankerRoundUp(mp_int *, mp_int *, int);
static int		ShouldBankerRoundUpToNext(mp_int *, mp_int *,
			    mp_int *, int, int, mp_int *);
static char *		ShorteningBignumConversion(Double *dPtr, int convType,
			    Tcl_WideUInt bw, int b2,
			    int m2plus, int m2minus,
			    int s2, int s5, int k, int len,
			    int ilim, int ilim1, int *decpt,
			    char **endPtr);
static char *		StrictBignumConversion(Double *dPtr, int convType,
			    Tcl_WideUInt bw, int b2,
			    int s2, int s5, int k, int len,
			    int ilim, int ilim1, int *decpt,
			    char **endPtr);
static double		BignumToBiasedFrExp(mp_int *big, int *machexp);
static double		Pow10TimesFrExp(int exponent, double fraction,
			    int *machexp);
static double		SafeLdExp(double fraction, int exponent);
static Tcl_WideUInt	Nokia770Twiddle(Tcl_WideUInt w);

/*







|


|



|
|

|
<
|
|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|



|
|
|


|
|
|
|
|
|



|
|
|


|
|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/*
 * Static functions defined in this file.
 */

static int		AccumulateDecimalDigit(unsigned, int,
			    Tcl_WideUInt *, mp_int *, int);
static double		MakeHighPrecisionDouble(int signum,
			    mp_int *significand, int nSigDigs, int exponent);
static double		MakeLowPrecisionDouble(int signum,
			    Tcl_WideUInt significand, int nSigDigs,
			    int exponent);
static double		MakeNaN(int signum, Tcl_WideUInt tag);
static double		RefineApproximation(double approx,
			    mp_int *exactSignificand, int exponent);
static void		MulPow5(mp_int*, unsigned, mp_int*);
static int 		NormalizeRightward(Tcl_WideUInt*);
static int		RequiredPrecision(Tcl_WideUInt);
static void		DoubleToExpAndSig(double, Tcl_WideUInt*, int*, int*);

static void		TakeAbsoluteValue(Double*, int*);
static char*		FormatInfAndNaN(Double*, int*, char**);
static char*		FormatZero(int*, char**);
static int		ApproximateLog10(Tcl_WideUInt, int, int);
static int		BetterLog10(double, int, int*);
static void		ComputeScale(int, int, int*, int*, int*, int*);
static void		SetPrecisionLimits(int, int, int*, int*, int*, int*);

static char*		BumpUp(char*, char*, int*);
static int		AdjustRange(double*, int);
static char*		ShorteningQuickFormat(double, int, int, double,
			    char*, int*);
static char*		StrictQuickFormat(double, int, int, double,
			    char*, int*);
static char*		QuickConversion(double, int, int, int, int, int, int,
			    int*, char**);
static void		CastOutPowersOf2(int*, int*, int*);
static char*		ShorteningInt64Conversion(Double*, int, Tcl_WideUInt,
			    int, int, int, int, int, int, int, int, int,
			    int, int, int*, char**);
static char*		StrictInt64Conversion(Double*, int, Tcl_WideUInt,
			    int, int, int, int, int, int,
			    int, int, int*, char**);
static int		ShouldBankerRoundUpPowD(mp_int*, int, int);
static int		ShouldBankerRoundUpToNextPowD(mp_int*, mp_int*,
			    int, int, int, mp_int*);
static char*		ShorteningBignumConversionPowD(Double* dPtr,
			    int convType, Tcl_WideUInt bw, int b2, int b5,
			    int m2plus, int m2minus, int m5,
			    int sd, int k, int len,
			    int ilim, int ilim1, int* decpt,
			    char** endPtr);
static char*		StrictBignumConversionPowD(Double* dPtr, int convType,
			    Tcl_WideUInt bw, int b2, int b5,
			    int sd, int k, int len,
			    int ilim, int ilim1, int* decpt,
			    char** endPtr);
static int		ShouldBankerRoundUp(mp_int*, mp_int*, int);
static int		ShouldBankerRoundUpToNext(mp_int*, mp_int*, mp_int*,
			    int, int, mp_int*);
static char*		ShorteningBignumConversion(Double* dPtr, int convType,
			    Tcl_WideUInt bw, int b2,
			    int m2plus, int m2minus,
			    int s2, int s5, int k, int len,
			    int ilim, int ilim1, int* decpt,
			    char** endPtr);
static char*		StrictBignumConversion(Double* dPtr, int convType,
			    Tcl_WideUInt bw, int b2,
			    int s2, int s5, int k, int len,
			    int ilim, int ilim1, int* decpt,
			    char** endPtr);
static double		BignumToBiasedFrExp(mp_int *big, int *machexp);
static double		Pow10TimesFrExp(int exponent, double fraction,
			    int *machexp);
static double		SafeLdExp(double fraction, int exponent);
static Tcl_WideUInt	Nokia770Twiddle(Tcl_WideUInt w);

/*
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
 *
 *	- TCL_PARSE_INTEGER_ONLY:	accept only integer values; reject
 *		strings that denote floating point values (or accept only the
 *		leading portion of them that are integer values).
 *	- TCL_PARSE_SCAN_PREFIXES:	ignore the prefixes 0b and 0o that are
 *		not part of the [scan] command's vocabulary. Use only in
 *		combination with TCL_PARSE_INTEGER_ONLY.
 *	- TCL_PARSE_OCTAL_ONLY:		parse only in the octal format, whether
 *		or not a prefix is present that would lead to octal parsing.
 *		Use only in combination with TCL_PARSE_INTEGER_ONLY.
 *	- TCL_PARSE_HEXADECIMAL_ONLY:	parse only in the hexadecimal format,
 *		whether or not a prefix is present that would lead to
 *		hexadecimal parsing. Use only in combination with
 *		TCL_PARSE_INTEGER_ONLY.
 *	- TCL_PARSE_DECIMAL_ONLY:	parse only in the decimal format, no
 *		matter whether a 0 prefix would normally force a different
 *		base.
 *	- TCL_PARSE_NO_WHITESPACE:	reject any leading/trailing whitespace
 *
 *	The arguments interp and expected are inputs that control error
 *	message generation. If interp is NULL, no error message will be
 *	generated. If interp is non-NULL, then expected must also be non-NULL.







|


|



|







356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
 *
 *	- TCL_PARSE_INTEGER_ONLY:	accept only integer values; reject
 *		strings that denote floating point values (or accept only the
 *		leading portion of them that are integer values).
 *	- TCL_PARSE_SCAN_PREFIXES:	ignore the prefixes 0b and 0o that are
 *		not part of the [scan] command's vocabulary. Use only in
 *		combination with TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_OCTAL_ONLY:		parse only in the octal format, whether
 *		or not a prefix is present that would lead to octal parsing.
 *		Use only in combination with TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_HEXADECIMAL_ONLY:	parse only in the hexadecimal format,
 *		whether or not a prefix is present that would lead to
 *		hexadecimal parsing. Use only in combination with
 *		TCL_PARSE_INTEGER_ONLY.
 * 	- TCL_PARSE_DECIMAL_ONLY:	parse only in the decimal format, no
 *		matter whether a 0 prefix would normally force a different
 *		base.
 *	- TCL_PARSE_NO_WHITESPACE:	reject any leading/trailing whitespace
 *
 *	The arguments interp and expected are inputs that control error
 *	message generation. If interp is NULL, no error message will be
 *	generated. If interp is non-NULL, then expected must also be non-NULL.
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
	sI, sIN, sINF, sINFI, sINFIN, sINFINI, sINFINIT, sINFINITY
#ifdef IEEE_FLOATING_POINT
	, sN, sNA, sNAN, sNANPAREN, sNANHEX, sNANFINISH
#endif
    } state = INITIAL;
    enum State acceptState = INITIAL;

    int signum = 0;		/* Sign of the number being parsed. */
    Tcl_WideUInt significandWide = 0;
				/* Significand of the number being parsed (if
				 * no overflow). */
    mp_int significandBig;	/* Significand of the number being parsed (if
				 * it overflows significandWide). */
    int significandOverflow = 0;/* Flag==1 iff significandBig is used. */
    Tcl_WideUInt octalSignificandWide = 0;
				/* Significand of an octal number; needed
				 * because we don't know whether a number with
				 * a leading zero is octal or decimal until
				 * we've scanned forward to a '.' or 'e'. */
    mp_int octalSignificandBig;	/* Significand of octal number once
				 * octalSignificandWide overflows. */
    int octalSignificandOverflow = 0;
				/* Flag==1 if octalSignificandBig is used. */
    int numSigDigs = 0;		/* Number of significant digits in the decimal
				 * significand. */
    int numTrailZeros = 0;	/* Number of trailing zeroes at the current
				 * point in the parse. */
    int numDigitsAfterDp = 0;	/* Number of digits scanned after the decimal
				 * point. */
    int exponentSignum = 0;	/* Signum of the exponent of a floating point
				 * number. */
    long exponent = 0;		/* Exponent of a floating point number. */
    const char *p;		/* Pointer to next character to scan. */
    size_t len;			/* Number of characters remaining after p. */
    const char *acceptPoint;	/* Pointer to position after last character in
				 * an acceptable number. */
    size_t acceptLen;		/* Number of characters following that
				 * point. */
    int status = TCL_OK;	/* Status to return to caller. */
    char d = 0;			/* Last hexadecimal digit scanned; initialized
				 * to avoid a compiler warning. */
    int shift = 0;		/* Amount to shift when accumulating binary */
    int explicitOctal = 0;


#define MOST_BITS	(UWIDE_MAX >> 1)

    /*
     * Initialize bytes to start of the object's string rep if the caller
     * didn't pass anything else.
     */

    if (bytes == NULL) {







|


|

|
|




|

|

|

|



|

|
|
|
|

|


|





>
|







457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
	sI, sIN, sINF, sINFI, sINFIN, sINFINI, sINFINIT, sINFINITY
#ifdef IEEE_FLOATING_POINT
	, sN, sNA, sNAN, sNANPAREN, sNANHEX, sNANFINISH
#endif
    } state = INITIAL;
    enum State acceptState = INITIAL;

    int signum = 0;		/* Sign of the number being parsed */
    Tcl_WideUInt significandWide = 0;
				/* Significand of the number being parsed (if
				 * no overflow) */
    mp_int significandBig;	/* Significand of the number being parsed (if
				 * it overflows significandWide) */
    int significandOverflow = 0;/* Flag==1 iff significandBig is used */
    Tcl_WideUInt octalSignificandWide = 0;
				/* Significand of an octal number; needed
				 * because we don't know whether a number with
				 * a leading zero is octal or decimal until
				 * we've scanned forward to a '.' or 'e' */
    mp_int octalSignificandBig;	/* Significand of octal number once
				 * octalSignificandWide overflows */
    int octalSignificandOverflow = 0;
				/* Flag==1 if octalSignificandBig is used */
    int numSigDigs = 0;		/* Number of significant digits in the decimal
				 * significand */
    int numTrailZeros = 0;	/* Number of trailing zeroes at the current
				 * point in the parse. */
    int numDigitsAfterDp = 0;	/* Number of digits scanned after the decimal
				 * point */
    int exponentSignum = 0;	/* Signum of the exponent of a floating point
				 * number */
    long exponent = 0;		/* Exponent of a floating point number */
    const char *p;		/* Pointer to next character to scan */
    size_t len;			/* Number of characters remaining after p */
    const char *acceptPoint;	/* Pointer to position after last character in
				 * an acceptable number */
    size_t acceptLen;		/* Number of characters following that
				 * point. */
    int status = TCL_OK;	/* Status to return to caller */
    char d = 0;			/* Last hexadecimal digit scanned; initialized
				 * to avoid a compiler warning. */
    int shift = 0;		/* Amount to shift when accumulating binary */
    int explicitOctal = 0;

#define ALL_BITS	(~(Tcl_WideUInt)0)
#define MOST_BITS	(ALL_BITS >> 1)

    /*
     * Initialize bytes to start of the object's string rep if the caller
     * didn't pass anything else.
     */

    if (bytes == NULL) {
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

	case INITIAL:
	    /*
	     * Initial state. Acceptable characters are +, -, digits, period,
	     * I, N, and whitespace.
	     */

	    if (TclIsSpaceProcM(c)) {
		if (flags & TCL_PARSE_NO_WHITESPACE) {
		    goto endgame;
		}
		break;
	    } else if (c == '+') {
		state = SIGNUM;
		break;







|







520
521
522
523
524
525
526
527
528
529
530
531
532
533
534

	case INITIAL:
	    /*
	     * Initial state. Acceptable characters are +, -, digits, period,
	     * I, N, and whitespace.
	     */

	    if (TclIsSpaceProc(c)) {
		if (flags & TCL_PARSE_NO_WHITESPACE) {
		    goto endgame;
		}
		break;
	    } else if (c == '+') {
		state = SIGNUM;
		break;
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
#endif
	    }
	    goto endgame;

	case ZERO:
	    /*
	     * Scanned a leading zero (perhaps with a + or -). Acceptable
	     * inputs are digits, period, X, b, and E. If 8 or 9 is
	     * encountered, the number can't be octal. This state and the
	     * OCTAL state differ only in whether they recognize 'X' and 'b'.
	     */

	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == 'x' || c == 'X') {
		if (flags & TCL_PARSE_OCTAL_ONLY) {







|
|
|







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
#endif
	    }
	    goto endgame;

	case ZERO:
	    /*
	     * Scanned a leading zero (perhaps with a + or -). Acceptable
	     * inputs are digits, period, X, b, and E. If 8 or 9 is encountered,
	     * the number can't be octal. This state and the OCTAL state
	     * differ only in whether they recognize 'X' and 'b'.
	     */

	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == 'x' || c == 'X') {
		if (flags & TCL_PARSE_OCTAL_ONLY) {
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c-'0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);

		    if (!octalSignificandOverflow) {
			/*
			 * Shifting by as many or more bits than are in the
			 * value being shifted is undefined behavior. Check
			 * for too large shifts first.
			 */

			if ((octalSignificandWide != 0)
				&& (((size_t)shift >=
					CHAR_BIT*sizeof(Tcl_WideUInt))
				|| (octalSignificandWide >
					(UWIDE_MAX >> shift)))) {
			    octalSignificandOverflow = 1;
			    TclBNInitBignumFromWideUInt(&octalSignificandBig,
				    octalSignificandWide);
			}
		    }
		    if (!octalSignificandOverflow) {
			/*
			 * When the significand is 0, it is possible for the
			 * amount to be shifted to equal or exceed the width
			 * of the significand. Do not shift when the
			 * significand is 0 to avoid undefined behavior.
			 */

			if (octalSignificandWide != 0) {
			    octalSignificandWide <<= shift;
			}
			octalSignificandWide += c - '0';
		    } else {
			mp_mul_2d(&octalSignificandBig, shift,
				&octalSignificandBig);
			mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'),
				&octalSignificandBig);
		    }
		}







|
|
|






|






<
<
<
<
<
<
<
<
|
<
|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663








664

665
666
667
668
669
670
671
672
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c-'0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);

		    if (!octalSignificandOverflow) {
			/*
			 * Shifting by more bits than are in the value being
			 * shifted is at least de facto nonportable. Check for
			 * too large shifts first.
			 */

			if ((octalSignificandWide != 0)
				&& (((size_t)shift >=
					CHAR_BIT*sizeof(Tcl_WideUInt))
				|| (octalSignificandWide >
					(~(Tcl_WideUInt)0 >> shift)))) {
			    octalSignificandOverflow = 1;
			    TclBNInitBignumFromWideUInt(&octalSignificandBig,
				    octalSignificandWide);
			}
		    }
		    if (!octalSignificandOverflow) {








			octalSignificandWide =

				(octalSignificandWide << shift) + (c - '0');
		    } else {
			mp_mul_2d(&octalSignificandBig, shift,
				&octalSignificandBig);
			mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'),
				&octalSignificandBig);
		    }
		}
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
	    } else {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = 4 * (numTrailZeros + 1);
		if (!significandOverflow) {
		    /*
		     * Shifting by as many or more bits than are in the
		     * value being shifted is undefined behavior. Check
		     * for too large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > (UWIDE_MAX >> shift))) {
			significandOverflow = 1;
			TclBNInitBignumFromWideUInt(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */

		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		    significandWide += d;
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		    mp_add_d(&significandBig, (mp_digit) d, &significandBig);
		}
	    }
	    numTrailZeros = 0;
	    state = HEXADECIMAL;
	    break;

	case BINARY:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    /* FALLTHRU */
	case ZERO_B:
	    if (c == '0') {
		numTrailZeros++;
		state = BINARY;
		break;
	    } else if (c != '1') {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = numTrailZeros + 1;
		if (!significandOverflow) {
		    /*
		     * Shifting by as many or more bits than are in the
		     * value being shifted is undefined behavior. Check
		     * for too large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > (UWIDE_MAX >> shift))) {
			significandOverflow = 1;
			TclBNInitBignumFromWideUInt(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */

		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		    significandWide += 1;
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		    mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
		}
	    }
	    numTrailZeros = 0;
	    state = BINARY;







|
|
|




|






<
<
<
<
<
<
<
<
<
<
|













<












|
|
|




|






<
<
<
<
<
<
<
<
<
<
|







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780










781
782
783
784
785
786
787
788
789
790
791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820










821
822
823
824
825
826
827
828
	    } else {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = 4 * (numTrailZeros + 1);
		if (!significandOverflow) {
		    /*
		     * Shifting by more bits than are in the value being
		     * shifted is at least de facto nonportable. Check for too
		     * large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > (~(Tcl_WideUInt)0 >> shift))) {
			significandOverflow = 1;
			TclBNInitBignumFromWideUInt(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {










		    significandWide = (significandWide << shift) + d;
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		    mp_add_d(&significandBig, (mp_digit) d, &significandBig);
		}
	    }
	    numTrailZeros = 0;
	    state = HEXADECIMAL;
	    break;

	case BINARY:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;

	case ZERO_B:
	    if (c == '0') {
		numTrailZeros++;
		state = BINARY;
		break;
	    } else if (c != '1') {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = numTrailZeros + 1;
		if (!significandOverflow) {
		    /*
		     * Shifting by more bits than are in the value being
		     * shifted is at least de facto nonportable. Check for too
		     * large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > (~(Tcl_WideUInt)0 >> shift))) {
			significandOverflow = 1;
			TclBNInitBignumFromWideUInt(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {










		    significandWide = (significandWide << shift) + 1;
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		    mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
		}
	    }
	    numTrailZeros = 0;
	    state = BINARY;
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
	case sNANHEX:
	    if (c == ')') {
		state = sNANFINISH;
		break;
	    }
	    /* FALLTHROUGH */
	case sNANPAREN:
	    if (TclIsSpaceProcM(c)) {
		break;
	    }
	    if (numSigDigs < 13) {
		if (c >= '0' && c <= '9') {
		    d = c - '0';
		} else if (c >= 'a' && c <= 'f') {
		    d = 10 + c - 'a';







|







1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
	case sNANHEX:
	    if (c == ')') {
		state = sNANFINISH;
		break;
	    }
	    /* FALLTHROUGH */
	case sNANPAREN:
	    if (TclIsSpaceProc(c)) {
		break;
	    }
	    if (numSigDigs < 13) {
		if (c >= '0' && c <= '9') {
		    d = c - '0';
		} else if (c >= 'a' && c <= 'f') {
		    d = 10 + c - 'a';
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
	p = acceptPoint;
	len = acceptLen;
	if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
	    /*
	     * Accept trailing whitespace.
	     */

	    while (len != 0 && TclIsSpaceProcM(*p)) {
		p++;
		len--;
	    }
	}
	if (endPtrPtr == NULL) {
	    if ((len != 0) && ((numBytes > 0) || (*p != '\0'))) {
		status = TCL_ERROR;







|







1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
	p = acceptPoint;
	len = acceptLen;
	if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
	    /*
	     * Accept trailing whitespace.
	     */

	    while (len != 0 && TclIsSpaceProc(*p)) {
		p++;
		len--;
	    }
	}
	if (endPtrPtr == NULL) {
	    if ((len != 0) && ((numBytes > 0) || (*p != '\0'))) {
		status = TCL_ERROR;
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
	case sINFINI:
	case sINFINIT:
#ifdef IEEE_FLOATING_POINT
	case sN:
	case sNA:
	case sNANPAREN:
	case sNANHEX:
#endif
	    Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'",
		    acceptState, bytes);

	case BINARY:
	    shift = numTrailZeros;
	    if (!significandOverflow && significandWide != 0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		TclBNInitBignumFromWideUInt(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    goto returnInteger;

	case HEXADECIMAL:
	    /*
	     * Returning a hex integer. Final scaling step.
	     */

	    shift = 4 * numTrailZeros;
	    if (!significandOverflow && significandWide !=0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		TclBNInitBignumFromWideUInt(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    goto returnInteger;

	case OCTAL:
	    /*
	     * Returning an octal integer. Final scaling step.
	     */

	    shift = 3 * numTrailZeros;
	    if (!octalSignificandOverflow && octalSignificandWide != 0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    octalSignificandWide > (MOST_BITS + signum) >> shift)) {
		octalSignificandOverflow = 1;
		TclBNInitBignumFromWideUInt(&octalSignificandBig,
			octalSignificandWide);
	    }
	    if (shift) {
		if (!octalSignificandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (octalSignificandWide != 0) {
			octalSignificandWide <<= shift;
		    }
		} else {
		    mp_mul_2d(&octalSignificandBig, shift,
			    &octalSignificandBig);
		}
	    }
	    if (!octalSignificandOverflow) {
		if (octalSignificandWide >
			(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
#ifndef NO_WIDE_TYPE
		    if (octalSignificandWide <= (MOST_BITS + signum)) {
			objPtr->typePtr = &tclWideIntType;
			if (signum) {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) (-octalSignificandWide);
			} else {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) octalSignificandWide;
			}
			break;
		    }
#endif
		    TclBNInitBignumFromWideUInt(&octalSignificandBig,
			    octalSignificandWide);
		    octalSignificandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.longValue =
				(long) (-octalSignificandWide);
		    } else {
			objPtr->internalRep.longValue =
				(long) octalSignificandWide;
		    }
		}
	    }
	    if (octalSignificandOverflow) {
		if (signum) {
		    (void)mp_neg(&octalSignificandBig, &octalSignificandBig);
		}
		TclSetBignumIntRep(objPtr, &octalSignificandBig);
	    }
	    break;

	case ZERO:
	case DECIMAL:







<


>










<
<
<
<
<
<
<
|
<




















<
<
<
<
<
<
<
|
<








|












<
<
<
<
<
<
<
|
<













|














|








|







1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153







1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174







1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196







1197

1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
	case sINFINI:
	case sINFINIT:
#ifdef IEEE_FLOATING_POINT
	case sN:
	case sNA:
	case sNANPAREN:
	case sNANHEX:

	    Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'",
		    acceptState, bytes);
#endif
	case BINARY:
	    shift = numTrailZeros;
	    if (!significandOverflow && significandWide != 0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		TclBNInitBignumFromWideUInt(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {







		    significandWide <<= shift;

		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    goto returnInteger;

	case HEXADECIMAL:
	    /*
	     * Returning a hex integer. Final scaling step.
	     */

	    shift = 4 * numTrailZeros;
	    if (!significandOverflow && significandWide !=0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		TclBNInitBignumFromWideUInt(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {







		    significandWide <<= shift;

		} else {
		    mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    goto returnInteger;

	case OCTAL:
	    /*
	     * Returning an octal integer. Final scaling step
	     */

	    shift = 3 * numTrailZeros;
	    if (!octalSignificandOverflow && octalSignificandWide != 0 &&
		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    octalSignificandWide > (MOST_BITS + signum) >> shift)) {
		octalSignificandOverflow = 1;
		TclBNInitBignumFromWideUInt(&octalSignificandBig,
			octalSignificandWide);
	    }
	    if (shift) {
		if (!octalSignificandOverflow) {







		    octalSignificandWide <<= shift;

		} else {
		    mp_mul_2d(&octalSignificandBig, shift,
			    &octalSignificandBig);
		}
	    }
	    if (!octalSignificandOverflow) {
		if (octalSignificandWide >
			(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
#ifndef NO_WIDE_TYPE
		    if (octalSignificandWide <= (MOST_BITS + signum)) {
			objPtr->typePtr = &tclWideIntType;
			if (signum) {
			    objPtr->internalRep.wideValue =
				    - (Tcl_WideInt) octalSignificandWide;
			} else {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) octalSignificandWide;
			}
			break;
		    }
#endif
		    TclBNInitBignumFromWideUInt(&octalSignificandBig,
			    octalSignificandWide);
		    octalSignificandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.longValue =
				- (long) octalSignificandWide;
		    } else {
			objPtr->internalRep.longValue =
				(long) octalSignificandWide;
		    }
		}
	    }
	    if (octalSignificandOverflow) {
		if (signum) {
		    mp_neg(&octalSignificandBig, &octalSignificandBig);
		}
		TclSetBignumIntRep(objPtr, &octalSignificandBig);
	    }
	    break;

	case ZERO:
	case DECIMAL:
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
		if (significandWide >
			(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
#ifndef NO_WIDE_TYPE
		    if (significandWide <= MOST_BITS+signum) {
			objPtr->typePtr = &tclWideIntType;
			if (signum) {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) (-significandWide);
			} else {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) significandWide;
			}
			break;
		    }
#endif
		    TclBNInitBignumFromWideUInt(&significandBig,
			    significandWide);
		    significandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.longValue =
				(long) (-significandWide);
		    } else {
			objPtr->internalRep.longValue =
				(long) significandWide;
		    }
		}
	    }
	    if (significandOverflow) {
		if (signum) {
		    (void)mp_neg(&significandBig, &significandBig);
		}
		TclSetBignumIntRep(objPtr, &significandBig);
	    }
	    break;

	case FRACTION:
	case EXPONENT:

	    /*
	     * Here, we're parsing a floating-point number. 'significandWide'
	     * or 'significandBig' contains the exact significand, according
	     * to whether 'significandOverflow' is set. The desired floating
	     * point value is significand * 10**k, where
	     * k = numTrailZeros+exponent-numDigitsAfterDp.
	     */

	    objPtr->typePtr = &tclDoubleType;
	    if (exponentSignum) {
		/*
		 * At this point exponent>=0, so the following calculation
		 * cannot underflow.
		 */
		exponent = -exponent;
	    }

	    /*
	     * Adjust the exponent for the number of trailing zeros that
	     * have not been accumulated, and the number of digits after
	     * the decimal point. Pin any overflow to LONG_MAX/LONG_MIN
	     * respectively.
	     */

	    if (exponent >= 0) {
		if (exponent - numDigitsAfterDp > LONG_MAX - numTrailZeros) {
		    exponent = LONG_MAX;
		} else {
		    exponent = exponent - numDigitsAfterDp + numTrailZeros;
		}
	    } else {
		if (exponent + numTrailZeros < LONG_MIN + numDigitsAfterDp) {
		    exponent = LONG_MIN;
		} else {
		    exponent = exponent + numTrailZeros - numDigitsAfterDp;
		}
	    }

	    /*
	     * The desired number is now significandWide * 10**exponent
	     * or significandBig * 10**exponent, depending on whether
	     * the significand has overflowed a wide int.
	     */
	    if (!significandOverflow) {
		objPtr->internalRep.doubleValue = MakeLowPrecisionDouble(
			signum, significandWide, numSigDigs, exponent);

	    } else {
		objPtr->internalRep.doubleValue = MakeHighPrecisionDouble(
			signum, &significandBig, numSigDigs, exponent);

	    }
	    break;

	case sINF:
	case sINFINITY:
	    if (signum) {
		objPtr->internalRep.doubleValue = -HUGE_VAL;







|














|








|


















<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
>


|
>







1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300




1301
1302



























1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
		if (significandWide >
			(Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
#ifndef NO_WIDE_TYPE
		    if (significandWide <= MOST_BITS+signum) {
			objPtr->typePtr = &tclWideIntType;
			if (signum) {
			    objPtr->internalRep.wideValue =
				    - (Tcl_WideInt) significandWide;
			} else {
			    objPtr->internalRep.wideValue =
				    (Tcl_WideInt) significandWide;
			}
			break;
		    }
#endif
		    TclBNInitBignumFromWideUInt(&significandBig,
			    significandWide);
		    significandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.longValue =
				- (long) significandWide;
		    } else {
			objPtr->internalRep.longValue =
				(long) significandWide;
		    }
		}
	    }
	    if (significandOverflow) {
		if (signum) {
		    mp_neg(&significandBig, &significandBig);
		}
		TclSetBignumIntRep(objPtr, &significandBig);
	    }
	    break;

	case FRACTION:
	case EXPONENT:

	    /*
	     * Here, we're parsing a floating-point number. 'significandWide'
	     * or 'significandBig' contains the exact significand, according
	     * to whether 'significandOverflow' is set. The desired floating
	     * point value is significand * 10**k, where
	     * k = numTrailZeros+exponent-numDigitsAfterDp.
	     */

	    objPtr->typePtr = &tclDoubleType;
	    if (exponentSignum) {




		exponent = - exponent;
	    }



























	    if (!significandOverflow) {
		objPtr->internalRep.doubleValue = MakeLowPrecisionDouble(
			signum, significandWide, numSigDigs,
			(numTrailZeros + exponent - numDigitsAfterDp));
	    } else {
		objPtr->internalRep.doubleValue = MakeHighPrecisionDouble(
			signum, &significandBig, numSigDigs,
			(numTrailZeros + exponent - numDigitsAfterDp));
	    }
	    break;

	case sINF:
	case sINFINITY:
	    if (signum) {
		objPtr->internalRep.doubleValue = -HUGE_VAL;
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
	case sNAN:
	case sNANFINISH:
	    objPtr->internalRep.doubleValue = MakeNaN(signum, significandWide);
	    objPtr->typePtr = &tclDoubleType;
	    break;
#endif
	case INITIAL:
	    /* This case only to silence compiler warning. */
	    Tcl_Panic("TclParseNumber: state INITIAL can't happen here");
	}
    }

    /*
     * Format an error message when an invalid number is encountered.
     */







|







1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
	case sNAN:
	case sNANFINISH:
	    objPtr->internalRep.doubleValue = MakeNaN(signum, significandWide);
	    objPtr->typePtr = &tclDoubleType;
	    break;
#endif
	case INITIAL:
	    /* This case only to silence compiler warning */
	    Tcl_Panic("TclParseNumber: state INITIAL can't happen here");
	}
    }

    /*
     * Format an error message when an invalid number is encountered.
     */
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
    int bignumFlag)		/* Flag == 1 if the number overflowed previous
				 * to this digit. */
{
    int i, n;
    Tcl_WideUInt w;

    /*
     * Try wide multiplication first.
     */

    if (!bignumFlag) {
	w = *wideRepPtr;
	if (w == 0) {
	    /*
	     * There's no need to multiply if the multiplicand is zero.
	     */

	    *wideRepPtr = digit;
	    return 0;
	} else if (numZeros >= maxpow10_wide
		|| w > (UWIDE_MAX-digit)/pow10_wide[numZeros+1]) {
	    /*
	     * Wide multiplication will overflow.  Expand the number to a
	     * bignum and fall through into the bignum case.
	     */

	    TclBNInitBignumFromWideUInt(bignumRepPtr, w);
	} else {
	    /*
	     * Wide multiplication.
	     */

	    *wideRepPtr = w * pow10_wide[numZeros+1] + digit;
	    return 0;
	}
    }

    /*
     * Bignum multiplication.







|












|

|
|







<







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
    int bignumFlag)		/* Flag == 1 if the number overflowed previous
				 * to this digit. */
{
    int i, n;
    Tcl_WideUInt w;

    /*
     * Try wide multiplication first
     */

    if (!bignumFlag) {
	w = *wideRepPtr;
	if (w == 0) {
	    /*
	     * There's no need to multiply if the multiplicand is zero.
	     */

	    *wideRepPtr = digit;
	    return 0;
	} else if (numZeros >= maxpow10_wide
		  || w > ((~(Tcl_WideUInt)0)-digit)/pow10_wide[numZeros+1]) {
	    /*
	     * Wide multiplication will overflow.  Expand the
	     * number to a bignum and fall through into the bignum case.
	     */

	    TclBNInitBignumFromWideUInt(bignumRepPtr, w);
	} else {
	    /*
	     * Wide multiplication.
	     */

	    *wideRepPtr = w * pow10_wide[numZeros+1] + digit;
	    return 0;
	}
    }

    /*
     * Bignum multiplication.
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
		bignumRepPtr);
	mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
    } else {
	/*
	 * More than single digit multiplication. Multiply by the appropriate
	 * small powers of 5, and then shift. Large strings of zeroes are
	 * eaten 256 at a time; this is less efficient than it could be, but
	 * seems implausible. We presume that MP_DIGIT_BIT is at least 27. The
	 * first multiplication, by up to 10**7, is done with a one-DIGIT
	 * multiply (this presumes that MP_DIGIT_BIT >= 24).
	 */

	n = numZeros + 1;
	mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
	for (i=3; i<=7; ++i) {
	    if (n & (1 << i)) {
		mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);







|

|







1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
		bignumRepPtr);
	mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
    } else {
	/*
	 * More than single digit multiplication. Multiply by the appropriate
	 * small powers of 5, and then shift. Large strings of zeroes are
	 * eaten 256 at a time; this is less efficient than it could be, but
	 * seems implausible. We presume that DIGIT_BIT is at least 27. The
	 * first multiplication, by up to 10**7, is done with a one-DIGIT
	 * multiply (this presumes that DIGIT_BIT >= 24).
	 */

	n = numZeros + 1;
	mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
	for (i=3; i<=7; ++i) {
	    if (n & (1 << i)) {
		mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);
1610
1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631



1632
1633
1634
1635

1636

1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
 */

static double
MakeLowPrecisionDouble(
    int signum,			/* 1 if the number is negative, 0 otherwise */
    Tcl_WideUInt significand,	/* Significand of the number */
    int numSigDigs,		/* Number of digits in the significand */
    long exponent)		/* Power of ten */
{

    mp_int significandBig;	/* Significand expressed as a bignum. */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits. We also make
     * 'retval' volatile, so that it doesn't get promoted to a register.
     */
    volatile double retval;		/* Value of the number. */

    /*



     * Test for zero significand, which requires explicit construction
     * of -0.0. (Unary minus returns a positive zero.)
     */
    if (significand == 0) {

	return copysign(0.0, -signum);

    }

    /*
     * Set the FP control word for 53 bits, WARNING: It must be reset
     * before returning.
     */
    TCL_IEEE_DOUBLE_ROUNDING;

    if (numSigDigs <= QUICK_MAX) {
	if (exponent >= 0) {
	    if (exponent <= mmaxpow) {
		/*
		 * The significand is an exact integer, and so is
		 * 10**exponent. The product will be correct to within 1/2 ulp
		 * without special handling.
		 */

		retval = (double)
			((Tcl_WideInt)significand * pow10vals[exponent]);
		goto returnValue;
	    } else {
		int diff = QUICK_MAX - numSigDigs;

		if (exponent-diff <= mmaxpow) {
		    /*
		     * 10**exponent is not an exact integer, but
		     * 10**(exponent-diff) is exact, and so is
		     * significand*10**diff, so we can still compute the value
		     * with only one roundoff.
		     */

		    volatile double factor = (double)
			    ((Tcl_WideInt)significand * pow10vals[diff]);
		    retval = factor * pow10vals[exponent-diff];
		    goto returnValue;
		}
	    }
	} else {
	    if (exponent >= -mmaxpow) {
		/*
		 * 10**-exponent is an exact integer, and so is the
		 * significand. Compute the result by one division, again with
		 * only one rounding.
		 */

		retval = (double)
			((Tcl_WideInt)significand / pow10vals[-exponent]);
		goto returnValue;
	    }
	}
    }

    /*
     * All the easy cases have failed. Promote ths significand to bignum and







|

>
|






|
<

<

<
>
>
>
|
|
<
|
>
|
>
|
<

<
|

<










<
|



<








|
|












<
|







1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507

1508

1509

1510
1511
1512
1513
1514

1515
1516
1517
1518
1519

1520

1521
1522

1523
1524
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1566
 */

static double
MakeLowPrecisionDouble(
    int signum,			/* 1 if the number is negative, 0 otherwise */
    Tcl_WideUInt significand,	/* Significand of the number */
    int numSigDigs,		/* Number of digits in the significand */
    int exponent)		/* Power of ten */
{
    double retval;		/* Value of the number */
    mp_int significandBig;	/* Significand expressed as a bignum */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits.

     */



#if defined(__GNUC__) && defined(__i386)
    fpu_control_t roundTo53Bits = 0x027f;
    fpu_control_t oldRoundingMode;
    _FPU_GETCW(oldRoundingMode);
    _FPU_SETCW(roundTo53Bits);

#endif
#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
    ieee_flags("set","precision","double",NULL);
#endif


    /*

     * Test for the easy cases.
     */


    if (numSigDigs <= QUICK_MAX) {
	if (exponent >= 0) {
	    if (exponent <= mmaxpow) {
		/*
		 * The significand is an exact integer, and so is
		 * 10**exponent. The product will be correct to within 1/2 ulp
		 * without special handling.
		 */


		retval = (double)(Tcl_WideInt)significand * pow10vals[exponent];
		goto returnValue;
	    } else {
		int diff = QUICK_MAX - numSigDigs;

		if (exponent-diff <= mmaxpow) {
		    /*
		     * 10**exponent is not an exact integer, but
		     * 10**(exponent-diff) is exact, and so is
		     * significand*10**diff, so we can still compute the value
		     * with only one roundoff.
		     */

		    volatile double factor =
			    (double)(Tcl_WideInt)significand * pow10vals[diff];
		    retval = factor * pow10vals[exponent-diff];
		    goto returnValue;
		}
	    }
	} else {
	    if (exponent >= -mmaxpow) {
		/*
		 * 10**-exponent is an exact integer, and so is the
		 * significand. Compute the result by one division, again with
		 * only one rounding.
		 */


		retval = (double)(Tcl_WideInt)significand / pow10vals[-exponent];
		goto returnValue;
	    }
	}
    }

    /*
     * All the easy cases have failed. Promote ths significand to bignum and
1705
1706
1707
1708
1709
1710
1711
1712





1713
1714
1715
1716
1717
1718
1719
	retval = -retval;
    }

    /*
     * On gcc on x86, restore the floating point mode word.
     */

    TCL_DEFAULT_DOUBLE_ROUNDING;






    return retval;
}

/*
 *----------------------------------------------------------------------
 *







|
>
>
>
>
>







1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
	retval = -retval;
    }

    /*
     * On gcc on x86, restore the floating point mode word.
     */

#if defined(__GNUC__) && defined(__i386)
    _FPU_SETCW(oldRoundingMode);
#endif
#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
    ieee_flags("clear","precision",NULL,NULL);
#endif

    return retval;
}

/*
 *----------------------------------------------------------------------
 *
1733
1734
1735
1736
1737
1738
1739
1740
1741

1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755




1756
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
 */

static double
MakeHighPrecisionDouble(
    int signum,			/* 1=negative, 0=nonnegative */
    mp_int *significand,	/* Exact significand of the number */
    int numSigDigs,		/* Number of significant digits */
    long exponent)		/* Power of 10 by which to multiply */
{

    int machexp;		/* Machine exponent of a power of 10. */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits. We also make
     * 'retval' volatile to make sure that it doesn't get promoted to a
     * register.
     */
    volatile double retval;

    /* 




     * A zero significand requires explicit construction of -0.0.
     * (Unary minus returns positive zero.)
     */
    if (mp_iszero(significand)) {
	return copysign(0.0, -signum);
    }

    /*
     * Set the 53-bit rounding mode. WARNING: It must be reset before

     * returning.
     */
    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Make quick checks for over/underflow. Be careful to avoid
     * integer overflow when calculating with 'exponent'.
     */

    if (exponent >= 0 && exponent-1 > maxDigits-numSigDigs) {
	retval = HUGE_VAL;
	goto returnValue;

    } else if (exponent < 0 && numSigDigs+exponent < minDigits+1) {
	retval = 0.0;
	goto returnValue;
    }

    /*
     * Develop a first approximation to the significand. It is tempting simply
     * to force bignum to double, but that will overflow on input numbers like
     * 1.[string repeat 0 1000]1; while this is a not terribly likely
     * scenario, we still have to deal with it. Use fraction and exponent
     * instead. Once we have the significand, multiply by 10**exponent. Test
     * for overflow. Convert back to a double, and test for underflow.
     */

    retval = BignumToBiasedFrExp(significand, &machexp);
    retval = Pow10TimesFrExp(exponent, retval, &machexp);
    if (machexp > DBL_MAX_EXP*log2FLT_RADIX) {
	retval = HUGE_VAL;
	goto returnValue;
    }
    retval = SafeLdExp(retval, machexp);
	if (tiny == 0.0) {
	    tiny = SafeLdExp(1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits);
	}
    if (retval < tiny) {
	retval = tiny;
    }

    /*
     * Refine the result twice. (The second refinement should be necessary
     * only if the best approximation is a power of 2 minus 1/2 ulp).







|

>
|






|
<
<

<

<
>
>
>
>
|
<
<
|
<
<
|
<
<
>
|
<
<


|
<

>
|


>
|
|



















|
|
|







1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631


1632

1633

1634
1635
1636
1637
1638


1639


1640


1641
1642


1643
1644
1645

1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
 */

static double
MakeHighPrecisionDouble(
    int signum,			/* 1=negative, 0=nonnegative */
    mp_int *significand,	/* Exact significand of the number */
    int numSigDigs,		/* Number of significant digits */
    int exponent)		/* Power of 10 by which to multiply */
{
    double retval;
    int machexp;		/* Machine exponent of a power of 10 */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits.


     */



#if defined(__GNUC__) && defined(__i386)
    fpu_control_t roundTo53Bits = 0x027f;
    fpu_control_t oldRoundingMode;
    _FPU_GETCW(oldRoundingMode);
    _FPU_SETCW(roundTo53Bits);


#endif


#if defined(__sun) && defined(__i386) && !defined(__GNUC__)


    ieee_flags("set","precision","double",NULL);
#endif



    /*
     * Quick checks for over/underflow.

     */

    if (numSigDigs+exponent-1 > maxDigits) {
	retval = HUGE_VAL;
	goto returnValue;
    }
    if (numSigDigs+exponent-1 < minDigits) {
	retval = 0;
	goto returnValue;
    }

    /*
     * Develop a first approximation to the significand. It is tempting simply
     * to force bignum to double, but that will overflow on input numbers like
     * 1.[string repeat 0 1000]1; while this is a not terribly likely
     * scenario, we still have to deal with it. Use fraction and exponent
     * instead. Once we have the significand, multiply by 10**exponent. Test
     * for overflow. Convert back to a double, and test for underflow.
     */

    retval = BignumToBiasedFrExp(significand, &machexp);
    retval = Pow10TimesFrExp(exponent, retval, &machexp);
    if (machexp > DBL_MAX_EXP*log2FLT_RADIX) {
	retval = HUGE_VAL;
	goto returnValue;
    }
    retval = SafeLdExp(retval, machexp);
    if (tiny == 0.0) {
	tiny = SafeLdExp(1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits);
    }
    if (retval < tiny) {
	retval = tiny;
    }

    /*
     * Refine the result twice. (The second refinement should be necessary
     * only if the best approximation is a power of 2 minus 1/2 ulp).
1818
1819
1820
1821
1822
1823
1824
1825
1826




1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
	retval = -retval;
    }

    /*
     * On gcc on x86, restore the floating point mode word.
     */

    TCL_DEFAULT_DOUBLE_ROUNDING;





    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeNaN --
 *
 *	Makes a "Not a Number" given a set of bits to put in the tag bits
 *
 *	Note that a signalling NaN is never returned.
 *
 *----------------------------------------------------------------------
 */

#ifdef IEEE_FLOATING_POINT
static double
MakeNaN(
    int signum,			/* Sign bit (1=negative, 0=nonnegative. */
    Tcl_WideUInt tags)		/* Tag bits to put in the NaN. */
{
    union {
	Tcl_WideUInt iv;
	double dv;
    } theNaN;

    theNaN.iv = tags;







|
|
>
>
>
>


















|
|







1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
	retval = -retval;
    }

    /*
     * On gcc on x86, restore the floating point mode word.
     */

#if defined(__GNUC__) && defined(__i386)
    _FPU_SETCW(oldRoundingMode);
#endif
#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
    ieee_flags("clear","precision",NULL,NULL);
#endif
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeNaN --
 *
 *	Makes a "Not a Number" given a set of bits to put in the tag bits
 *
 *	Note that a signalling NaN is never returned.
 *
 *----------------------------------------------------------------------
 */

#ifdef IEEE_FLOATING_POINT
static double
MakeNaN(
    int signum,			/* Sign bit (1=negative, 0=nonnegative */
    Tcl_WideUInt tags)	 	/* Tag bits to put in the NaN */
{
    union {
	Tcl_WideUInt iv;
	double dv;
    } theNaN;

    theNaN.iv = tags;
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959

1960


1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
 *	Returns the improved result.
 *
 *----------------------------------------------------------------------
 */

static double
RefineApproximation(
    double approxResult,	/* Approximate result of conversion. */
    mp_int *exactSignificand,	/* Integer significand. */
    int exponent)		/* Power of 10 to multiply by significand. */
{
    int M2, M5;			/* Powers of 2 and of 5 needed to put the
				 * decimal and binary numbers over a common
				 * denominator. */
    double significand;		/* Sigificand of the binary number. */
    int binExponent;		/* Exponent of the binary number. */
    int msb;			/* Most significant bit position of an
				 * intermediate result. */
    int nDigits;		/* Number of mp_digit's in an intermediate
				 * result. */
    mp_int twoMv;		/* Approx binary value expressed as an exact
				 * integer scaled by the multiplier 2M. */
    mp_int twoMd;		/* Exact decimal value expressed as an exact
				 * integer scaled by the multiplier 2M. */
    int scale;			/* Scale factor for M. */
    int multiplier;		/* Power of two to scale M. */
    double num, den;		/* Numerator and denominator of the correction
				 * term. */
    double quot;		/* Correction term. */
    double minincr;		/* Lower bound on the absolute value of the
				 * correction term. */
    int roundToEven = 0;	/* Flag == TRUE if we need to invoke
				 * "round to even" functionality */
    double rteSignificand;	/* Significand of the round-to-even result */
    int rteExponent;		/* Exponent of the round-to-even result */
    int shift;			/* Shift count for converting numerator
				 * and denominator of corrector to floating
				 * point */
    Tcl_WideInt rteSigWide;	/* Wide integer version of the significand
				 * for testing evenness */
    int i;

    /*
     * The first approximation is always low. If we find that it's HUGE_VAL,
     * we're done.
     */

    if (approxResult == HUGE_VAL) {
	return approxResult;
    }
    significand = frexp(approxResult, &binExponent);

    /*
     * We are trying to compute a corrector term that, when added to the
     * approximate result, will yield close to the exact result.
     * The exact result is exactSignificand * 10**exponent.
     * The approximate result is significand * 2**binExponent
     * If exponent<0, we need to multiply the exact value by 10**-exponent
     * to make it an integer, plus another factor of 2 to decide on rounding.
     *  Similarly if binExponent<FP_PRECISION, we need
     * to multiply by 2**FP_PRECISION to make the approximate value an integer.
     *

     * Let M = 2**M2 * 5**M5 be the least common multiple of these two
     * multipliers.
     */


    i = mantBits - binExponent;
    if (i < 0) {
	M2 = 0;
    } else {
	M2 = i;
    }
    if (exponent > 0) {
	M5 = 0;
    } else {
	M5 = -exponent;
	if (M5 - 1 > M2) {
	    M2 = M5 - 1;
	}
    }

    /*
     * Compute twoMv as 2*M*v, where v is the approximate value.

     * This is done by bit-whacking to calculate 2**(M2+1)*significand,


     * and then multiplying by 5**M5.
     */

    msb = binExponent + M2;	/* 1008 */
    nDigits = msb / MP_DIGIT_BIT + 1;
    mp_init_size(&twoMv, nDigits);
    i = (msb % MP_DIGIT_BIT + 1);
    twoMv.used = nDigits;
    significand *= SafeLdExp(1.0, i);
    while (--nDigits >= 0) {
	twoMv.dp[nDigits] = (mp_digit) significand;
	significand -= (mp_digit) significand;
	significand = SafeLdExp(significand, MP_DIGIT_BIT);
    }
    for (i = 0; i <= 8; ++i) {
	if (M5 & (1 << i)) {
	    mp_mul(&twoMv, pow5+i, &twoMv);
	}
    }

    /*
     * Compute twoMd as 2*M*d, where d is the exact value.
     * This is done by multiplying by 5**(M5+exponent) and then multiplying

     * by 2**(M5+exponent+1), which is, of couse, a left shift.
     */

    mp_init_copy(&twoMd, exactSignificand);
    for (i=0; i<=8; ++i) {
	if ((M5 + exponent) & (1 << i)) {
	    mp_mul(&twoMd, pow5+i, &twoMd);
	}
    }
    mp_mul_2d(&twoMd, M2+exponent+1, &twoMd);

    /*
     * Now let twoMd = twoMd - twoMv, the difference between the exact and
     * approximate values.
     */

    mp_sub(&twoMd, &twoMv, &twoMd);

    /*
     * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction
     * term. Because 2M may well overflow a double, we need to scale the
     * denominator by a factor of 2**binExponent-mantBits. Place that factor
     * times 1/2 ULP into twoMd.
     */

    scale = binExponent - mantBits - 1;

    mp_set(&twoMv, 1);
    for (i=0; i<=8; ++i) {
	if (M5 & (1 << i)) {
	    mp_mul(&twoMv, pow5+i, &twoMv);
	}
    }
    multiplier = M2 + scale + 1;
    if (multiplier > 0) {
	mp_mul_2d(&twoMv, multiplier, &twoMv);
    } else if (multiplier < 0) {
	mp_div_2d(&twoMv, -multiplier, &twoMv, NULL);
    }

    /*
     * Will the eventual correction term be less than, equal to, or
     * greater than 1/2 ULP?
     */

    switch (mp_cmp_mag(&twoMd, &twoMv)) {
    case MP_LT:
	/*

	 * If the error is less than 1/2 ULP, there's no correction to make.
	 */
	mp_clear(&twoMd);
	mp_clear(&twoMv);
	return approxResult;
    case MP_EQ:
	/*
	 * If the error is exactly 1/2 ULP, we need to round to even.
	 */
	roundToEven = 1;
	break;
    case MP_GT:
	/*
	 * We need to correct the result if the error exceeds 1/2 ULP.
	 */
	break;
    }

    /*
     * If we're in the 'round to even' case, and the significand is already
     * even, we're done. Return the approximate result.
     */
    if (roundToEven) {
	rteSignificand = frexp(approxResult, &rteExponent);
	rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION);
	if ((rteSigWide & 1) == 0) {
	    mp_clear(&twoMd);
	    mp_clear(&twoMv);
	    return approxResult;
	}
    }

    /*
     * Reduce the numerator and denominator of the corrector term so that
     * they will fit in the floating point precision.
     */
    shift = mp_count_bits(&twoMv) - FP_PRECISION - 1;
    if (shift > 0) {
	mp_div_2d(&twoMv, shift, &twoMv, NULL);
	mp_div_2d(&twoMd, shift, &twoMd, NULL);
    }

    /*
     * Convert the numerator and denominator of the corrector term accurately
     * to floating point numbers.
     */

    num = TclBignumToDouble(&twoMd);
    den = TclBignumToDouble(&twoMv);







|
|
|




|
|

|

|

|

|
|
|

|
|






<
<
<












<


<
<
<
<
<
<
<
<
<
>
|
<


>










|
|




|
>
|
>
>
|



|

|





|








|
|
>
|




|




<
<
<
<
<
<





|
<



>













<
<
<
<
<



>
|

|
|



|




<
<
<



<
<
<
<




|
|




<
<
<
<
<
<
<
<
<
<







1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791



1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803

1804
1805









1806
1807

1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865






1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888





1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904



1905
1906
1907




1908
1909
1910
1911
1912
1913
1914
1915
1916
1917










1918
1919
1920
1921
1922
1923
1924
 *	Returns the improved result.
 *
 *----------------------------------------------------------------------
 */

static double
RefineApproximation(
    double approxResult,	/* Approximate result of conversion */
    mp_int *exactSignificand,	/* Integer significand */
    int exponent)		/* Power of 10 to multiply by significand */
{
    int M2, M5;			/* Powers of 2 and of 5 needed to put the
				 * decimal and binary numbers over a common
				 * denominator. */
    double significand;		/* Sigificand of the binary number */
    int binExponent;		/* Exponent of the binary number */
    int msb;			/* Most significant bit position of an
				 * intermediate result */
    int nDigits;		/* Number of mp_digit's in an intermediate
				 * result */
    mp_int twoMv;		/* Approx binary value expressed as an exact
				 * integer scaled by the multiplier 2M */
    mp_int twoMd;		/* Exact decimal value expressed as an exact
				 * integer scaled by the multiplier 2M */
    int scale;			/* Scale factor for M */
    int multiplier;		/* Power of two to scale M */
    double num, den;		/* Numerator and denominator of the correction
				 * term */
    double quot;		/* Correction term */
    double minincr;		/* Lower bound on the absolute value of the
				 * correction term. */
    int roundToEven = 0;	/* Flag == TRUE if we need to invoke
				 * "round to even" functionality */
    double rteSignificand;	/* Significand of the round-to-even result */
    int rteExponent;		/* Exponent of the round-to-even result */



    Tcl_WideInt rteSigWide;	/* Wide integer version of the significand
				 * for testing evenness */
    int i;

    /*
     * The first approximation is always low. If we find that it's HUGE_VAL,
     * we're done.
     */

    if (approxResult == HUGE_VAL) {
	return approxResult;
    }


    /*









     * Find a common denominator for the decimal and binary fractions. The
     * common denominator will be 2**M2 + 5**M5.

     */

    significand = frexp(approxResult, &binExponent);
    i = mantBits - binExponent;
    if (i < 0) {
	M2 = 0;
    } else {
	M2 = i;
    }
    if (exponent > 0) {
	M5 = 0;
    } else {
	M5 = -exponent;
	if ((M5-1) > M2) {
	    M2 = M5-1;
	}
    }

    /*
     * The floating point number is significand*2**binExponent. Compute the
     * large integer significand*2**(binExponent+M2+1). The 2**-1 bit of the
     * significand (the most significant) corresponds to the
     * 2**(binExponent+M2 + 1) bit of 2*M2*v. Allocate enough digits to hold
     * that quantity, then convert the significand to a large integer, scaled
     * appropriately. Then multiply by the appropriate power of 5.
     */

    msb = binExponent + M2;	/* 1008 */
    nDigits = msb / DIGIT_BIT + 1;
    mp_init_size(&twoMv, nDigits);
    i = (msb % DIGIT_BIT + 1);
    twoMv.used = nDigits;
    significand *= SafeLdExp(1.0, i);
    while (--nDigits >= 0) {
	twoMv.dp[nDigits] = (mp_digit) significand;
	significand -= (mp_digit) significand;
	significand = SafeLdExp(significand, DIGIT_BIT);
    }
    for (i = 0; i <= 8; ++i) {
	if (M5 & (1 << i)) {
	    mp_mul(&twoMv, pow5+i, &twoMv);
	}
    }

    /*
     * Collect the decimal significand as a high precision integer. The least
     * significant bit corresponds to bit M2+exponent+1 so it will need to be
     * shifted left by that many bits after being multiplied by
     * 5**(M5+exponent).
     */

    mp_init_copy(&twoMd, exactSignificand);
    for (i=0; i<=8; ++i) {
	if ((M5+exponent) & (1 << i)) {
	    mp_mul(&twoMd, pow5+i, &twoMd);
	}
    }
    mp_mul_2d(&twoMd, M2+exponent+1, &twoMd);






    mp_sub(&twoMd, &twoMv, &twoMd);

    /*
     * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction
     * term. Because 2M may well overflow a double, we need to scale the
     * denominator by a factor of 2**binExponent-mantBits

     */

    scale = binExponent - mantBits - 1;

    mp_set(&twoMv, 1);
    for (i=0; i<=8; ++i) {
	if (M5 & (1 << i)) {
	    mp_mul(&twoMv, pow5+i, &twoMv);
	}
    }
    multiplier = M2 + scale + 1;
    if (multiplier > 0) {
	mp_mul_2d(&twoMv, multiplier, &twoMv);
    } else if (multiplier < 0) {
	mp_div_2d(&twoMv, -multiplier, &twoMv, NULL);
    }






    switch (mp_cmp_mag(&twoMd, &twoMv)) {
    case MP_LT:
	/*
	 * If the result is less than unity, the error is less than 1/2 unit in
	 * the last place, so there's no correction to make.
	 */
        mp_clear(&twoMd);
        mp_clear(&twoMv);
	return approxResult;
    case MP_EQ:
	/*
	 * If the result is exactly unity, we need to round to even.
	 */
	roundToEven = 1;
	break;
    case MP_GT:



	break;
    }





    if (roundToEven) {
	rteSignificand = frexp(approxResult, &rteExponent);
	rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION);
	if ((rteSigWide & 1) == 0) {
            mp_clear(&twoMd);
            mp_clear(&twoMv);
	    return approxResult;
	}
    }











    /*
     * Convert the numerator and denominator of the corrector term accurately
     * to floating point numbers.
     */

    num = TclBignumToDouble(&twoMd);
    den = TclBignumToDouble(&twoMv);
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247

2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320


2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418

2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541

2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552

2553

2554
2555

2556
2557
2558

2559
2560

2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
    mp_clear(&twoMd);
    mp_clear(&twoMv);

    return approxResult + quot;
}

/*
 *----------------------------------------------------------------------
 *
 * MultPow5 --
 *
 *	Multiply a bignum by a power of 5.
 *
 * Side effects:
 *	Stores base*5**n in result.
 *
 *----------------------------------------------------------------------
 */

static inline void
MulPow5(
    mp_int *base, 		/* Number to multiply. */
    unsigned n,			/* Power of 5 to multiply by. */
    mp_int *result)		/* Place to store the result. */
{
    mp_int *p = base;
    int n13 = n / 13;
    int r = n % 13;

    if (r != 0) {
	mp_mul_d(p, dpow5[r], result);
	p = result;
    }
    r = 0;
    while (n13 != 0) {
	if (n13 & 1) {
	    mp_mul(p, pow5_13+r, result);
	    p = result;
	}
	n13 >>= 1;
	++r;
    }
    if (p != result) {
	mp_copy(p, result);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NormalizeRightward --
 *
 *	Shifts a number rightward until it is odd (that is, until the least
 *	significant bit is nonzero.
 *
 * Results:
 *	Returns the number of bit positions by which the number was shifted.
 *
 * Side effects:
 *	Shifts the number in place; *wPtr is replaced by the shifted number.
 *
 *----------------------------------------------------------------------
 */

static inline int
NormalizeRightward(
    Tcl_WideUInt *wPtr)		/* INOUT: Number to shift. */
{
    int rv = 0;
    Tcl_WideUInt w = *wPtr;

    if (!(w & (Tcl_WideUInt) 0xFFFFFFFF)) {
	w >>= 32; rv += 32;
    }
    if (!(w & (Tcl_WideUInt) 0xFFFF)) {
	w >>= 16; rv += 16;
    }
    if (!(w & (Tcl_WideUInt) 0xFF)) {
	w >>= 8; rv += 8;
    }
    if (!(w & (Tcl_WideUInt) 0xF)) {
	w >>= 4; rv += 4;
    }
    if (!(w & 0x3)) {
	w >>= 2; rv += 2;
    }
    if (!(w & 0x1)) {
	w >>= 1; ++rv;
    }
    *wPtr = w;
    return rv;
}

/*
 *----------------------------------------------------------------------
 *
 * RequiredPrecision --
 *
 *	Determines the number of bits needed to hold an intger.
 *
 * Results:
 *	Returns the position of the most significant bit (0 - 63).  Returns 0
 *	if the number is zero.
 *
 *----------------------------------------------------------------------
 */

static int
RequiredPrecision(
    Tcl_WideUInt w)		/* Number to interrogate. */
{
    int rv;
    unsigned long wi;

    if (w & ((Tcl_WideUInt) 0xFFFFFFFF << 32)) {
	wi = (unsigned long) (w >> 32); rv = 32;
    } else {
	wi = (unsigned long) w; rv = 0;
    }
    if (wi & 0xFFFF0000) {
	wi >>= 16; rv += 16;
    }
    if (wi & 0xFF00) {
	wi >>= 8; rv += 8;
    }
    if (wi & 0xF0) {
	wi >>= 4; rv += 4;
    }
    if (wi & 0xC) {
	wi >>= 2; rv += 2;
    }
    if (wi & 0x2) {
	wi >>= 1; ++rv;
    }
    if (wi & 0x1) {
	++rv;
    }
    return rv;
}

/*
 *----------------------------------------------------------------------
 *
 * DoubleToExpAndSig --
 *
 *	Separates a 'double' into exponent and significand.
 *
 * Side effects:
 *	Stores the significand in '*significand' and the exponent in '*expon'
 *	so that dv == significand * 2.0**expon, and significand is odd.  Also
 *	stores the position of the leftmost 1-bit in 'significand' in 'bits'.

 *
 *----------------------------------------------------------------------
 */

static inline void
DoubleToExpAndSig(
    double dv,			/* Number to convert. */

    Tcl_WideUInt *significand,	/* OUTPUT: Significand of the number. */
    int *expon,			/* OUTPUT: Exponent to multiply the number
				 * by. */
    int *bits)			/* OUTPUT: Number of significant bits. */
{
    Double d;			/* Number being converted. */
    Tcl_WideUInt z;		/* Significand under construction. */
    int de;			/* Exponent of the number. */
    int k;			/* Bit count. */

    d.d = dv;

    /*
     * Extract exponent and significand.
     */

    de = (d.w.word0 & EXP_MASK) >> EXP_SHIFT;
    z = d.q & SIG_MASK;
    if (de != 0) {
	z |= HIDDEN_BIT;
	k = NormalizeRightward(&z);
	*bits = FP_PRECISION - k;
	*expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1);
    } else {
	k = NormalizeRightward(&z);
	*expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1) + 1;
	*bits = RequiredPrecision(z);
    }
    *significand = z;
}

/*
 *----------------------------------------------------------------------
 *
 * TakeAbsoluteValue --
 *
 *	Takes the absolute value of a 'double' including 0, Inf and NaN
 *
 * Side effects:
 *	The 'double' in *d is replaced with its absolute value. The signum is
 *	stored in 'sign': 1 for negative, 0 for nonnegative.
 *
 *----------------------------------------------------------------------
 */

static inline void
TakeAbsoluteValue(
    Double *d,			/* Number to replace with absolute value. */
    int *sign)			/* Place to put the signum. */
{
    if (d->w.word0 & SIGN_BIT) {
	*sign = 1;
	d->w.word0 &= ~SIGN_BIT;
    } else {
	*sign = 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FormatInfAndNaN --
 *
 *	Bailout for formatting infinities and Not-A-Number.
 *
 * Results:
 *	Returns one of the strings 'Infinity' and 'NaN'.  The string returned
 *	must be freed by the caller using 'ckfree'.
 *
 * Side effects:
 *	Stores 9999 in *decpt, and sets '*endPtr' to designate the terminating
 *	NUL byte of the string if 'endPtr' is not NULL.
 *


 *----------------------------------------------------------------------
 */

static inline char *
FormatInfAndNaN(
    Double *d,			/* Exceptional number to format. */
    int *decpt,			/* Decimal point to set to a bogus value. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval;

    *decpt = 9999;
    if (!(d->w.word1) && !(d->w.word0 & HI_ORDER_SIG_MASK)) {
	retval = ckalloc(9);
	strcpy(retval, "Infinity");
	if (endPtr) {
	    *endPtr = retval + 8;
	}
    } else {
	retval = ckalloc(4);
	strcpy(retval, "NaN");
	if (endPtr) {
	    *endPtr = retval + 3;
	}
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * FormatZero --
 *
 *	Bailout to format a zero floating-point number.
 *
 * Results:
 *	Returns the constant string "0"
 *
 * Side effects:
 *	Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating
 *	the string in '*endPtr' if 'endPtr' is not NULL.
 *
 *----------------------------------------------------------------------
 */

static inline char *
FormatZero(
    int *decpt,			/* Location of the decimal point. */
    char **endPtr)		/* Pointer to the end of the formatted data */
{
    char *retval = ckalloc(2);

    strcpy(retval, "0");
    if (endPtr) {
	*endPtr = retval+1;
    }
    *decpt = 0;
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * ApproximateLog10 --
 *
 *	Computes a two-term Taylor series approximation to the common log of a
 *	number, and computes the number's binary log.
 *
 * Results:
 *	Return an approximation to floor(log10(bw*2**be)) that is either exact
 *	or 1 too high.
 *
 *----------------------------------------------------------------------
 */

static inline int
ApproximateLog10(
    Tcl_WideUInt bw,		/* Integer significand of the number. */
    int be,			/* Power of two to scale bw. */
    int bbits)			/* Number of bits of precision in bw. */
{
    int i;			/* Log base 2 of the number. */
    int k;			/* Floor(Log base 10 of the number) */
    double ds;			/* Mantissa of the number. */
    Double d2;

    /*
     * Compute i and d2 such that d = d2*2**i, and 1 < d2 < 2.
     * Compute an approximation to log10(d),
     *   log10(d) ~ log10(2) * i + log10(1.5)
     *            + (significand-1.5)/(1.5 * log(10))
     */

    d2.q = bw << (FP_PRECISION - bbits) & SIG_MASK;
    d2.w.word0 |= (EXPONENT_BIAS) << EXP_SHIFT;
    i = be + bbits - 1;
    ds = (d2.d - 1.5) * TWO_OVER_3LOG10
	    + LOG10_3HALVES_PLUS_FUDGE + LOG10_2 * i;

    k = (int) ds;
    if (k > ds) {
	--k;
    }
    return k;
}

/*
 *----------------------------------------------------------------------
 *
 * BetterLog10 --
 *
 *	Improves the result of ApproximateLog10 for numbers in the range
 *	1 .. 10**(TEN_PMAX)-1
 *
 * Side effects:
 *	Sets k_check to 0 if the new result is known to be exact, and to 1 if
 *	it may still be one too high.
 *
 * Results:
 *	Returns the improved approximation to log10(d).
 *
 *----------------------------------------------------------------------
 */

static inline int
BetterLog10(
    double d,			/* Original number to format. */
    int k,			/* Characteristic(Log base 10) of the
				 * number. */
    int *k_check)		/* Flag == 1 if k is inexact. */
{
    /*
     * Performance hack. If k is in the range 0..TEN_PMAX, then we can use a
     * powers-of-ten table to check it.
     */

    if (k >= 0 && k <= TEN_PMAX) {
	if (d < tens[k]) {
	    k--;
	}
	*k_check = 0;
    } else {
	*k_check = 1;
    }
    return k;
}

/*
 *----------------------------------------------------------------------
 *
 * ComputeScale --
 *
 *	Prepares to format a floating-point number as decimal.
 *
 * Parameters:
 *	floor(log10*x) is k (or possibly k-1).  floor(log2(x) is i.  The
 *	significand of x requires bbits bits to represent.
 *
 * Results:
 *	Determines integers b2, b5, s2, s5 so that sig*2**b2*5**b5/2**s2*2**s5
 *	exactly represents the value of the x/10**k. This value will lie in
 *	the range [1 .. 10), and allows for computing successive digits by
 *	multiplying sig%10 by 10.
 *
 *----------------------------------------------------------------------
 */

static inline void
ComputeScale(
    int be,			/* Exponent part of number: d = bw * 2**be. */
    int k,			/* Characteristic of log10(number). */
    int *b2,			/* OUTPUT: Power of 2 in the numerator. */
    int *b5,			/* OUTPUT: Power of 5 in the numerator. */
    int *s2,			/* OUTPUT: Power of 2 in the denominator. */
    int *s5)			/* OUTPUT: Power of 5 in the denominator. */
{

    /*
     * Scale numerator and denominator powers of 2 so that the input binary
     * number is the ratio of integers.
     */

    if (be <= 0) {
	*b2 = 0;
	*s2 = -be;
    } else {
	*b2 = be;
	*s2 = 0;
    }

    /*
     * Scale numerator and denominator so that the output decimal number is
     * the ratio of integers.
     */

    if (k >= 0) {
	*b5 = 0;
	*s5 = k;
	*s2 += k;
    } else {
	*b2 -= k;
	*b5 = -k;
	*s5 = 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * SetPrecisionLimits --
 *
 *	Determines how many digits of significance should be computed (and,
 *	hence, how much memory need be allocated) for formatting a floating
 *	point number.
 *
 * Given that 'k' is floor(log10(x)):
 * if 'shortest' format is used, there will be at most 18 digits in the
 * result.
 * if 'F' format is used, there will be at most 'ndigits' + k + 1 digits
 * if 'E' format is used, there will be exactly 'ndigits' digits.
 *
 * Side effects:
 *	Adjusts '*ndigitsPtr' to have a valid value. Stores the maximum memory

 *	allocation needed in *iPtr.  Sets '*iLimPtr' to the limiting number of
 *	digits to convert if k has been guessed correctly, and '*iLim1Ptr' to
 *	the limiting number of digits to convert if k has been guessed to be
 *	one too high.
 *
 *----------------------------------------------------------------------
 */

static inline void
SetPrecisionLimits(
    int convType,		/* Type of conversion: TCL_DD_SHORTEST,

				 * TCL_DD_STEELE0, TCL_DD_E_FMT,

				 * TCL_DD_F_FMT. */
    int k,			/* Floor(log10(number to convert)) */

    int *ndigitsPtr,		/* IN/OUT: Number of digits requested (will be
				 *         adjusted if needed). */
    int *iPtr,			/* OUT: Maximum number of digits to return. */

    int *iLimPtr,		/* OUT: Number of digits of significance if
				 *      the bignum method is used.*/

    int *iLim1Ptr)		/* OUT: Number of digits of significance if
				 *      the quick method is used. */
{
    switch (convType) {
    case TCL_DD_SHORTEST0:
    case TCL_DD_STEELE0:
	*iLimPtr = *iLim1Ptr = -1;
	*iPtr = 18;
	*ndigitsPtr = 0;
	break;
    case TCL_DD_E_FORMAT:







|






|

|


|
<
|
|
|

|


<

















|

|



|
|







|


|
|
|



<
|


|


|


|











|

|






|
|

|



|
|



<
|




|


|


|


|










|

|






|
|
|
>

|


|
|
<
>
|
|
<
|

|
|
|
|



<
|
<















|

|






|
|

|


|
<
|
|








|

|






|
<


|
|

>
>
|


|
|
<
|
|

|
<
















|

|












|


|
<
|
|

|
<







|

|



|
|


|
|

|


|
|
|
|
|

|

|













|
>






|

|







|
|


|

|


|
<
|
|
<
|


|
|

<










|

|






|
|



|
|
|

|


|
<
|
|
|
|
|
|

>

|
|

<









|
|

<












|



|
|
|


|
<




|
>
|
|
|
<

|


|
|
|
>
|
>
|
|
>
|
|
|
>
|
|
>
|
|

|







1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088

2089
2090
2091

2092
2093
2094
2095
2096
2097
2098
2099
2100

2101

2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152

2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164

2165
2166
2167
2168

2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207

2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280

2281
2282

2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366

2367
2368
2369
2370
2371
2372
2373
2374
2375

2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
    mp_clear(&twoMd);
    mp_clear(&twoMv);

    return approxResult + quot;
}

/*
 *-----------------------------------------------------------------------------
 *
 * MultPow5 --
 *
 *	Multiply a bignum by a power of 5.
 *
 * Side effects:
 *	Stores base*5**n in result
 *
 *-----------------------------------------------------------------------------
 */

inline static void

MulPow5(mp_int* base, 		/* Number to multiply */
	 unsigned n,		/* Power of 5 to multiply by */
	 mp_int* result)	/* Place to store the result */
{
    mp_int* p = base;
    int n13 = n / 13;
    int r = n % 13;

    if (r != 0) {
	mp_mul_d(p, dpow5[r], result);
	p = result;
    }
    r = 0;
    while (n13 != 0) {
	if (n13 & 1) {
	    mp_mul(p, pow5_13+r, result);
	    p = result;
	}
	n13 >>= 1;
	++r;
    }
    if (p != result) {
	mp_copy(p, result);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * NormalizeRightward --
 *
 *	Shifts a number rightward until it is odd (that is, until the
 *	least significant bit is nonzero.
 *
 * Results:
 *	Returns the number of bit positions by which the number was shifted.
 *
 * Side effects:
 *	Shifts the number in place; *wPtr is replaced by the shifted number.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
NormalizeRightward(Tcl_WideUInt* wPtr)
				/* INOUT: Number to shift */
{
    int rv = 0;
    Tcl_WideUInt w = *wPtr;

    if (!(w & (Tcl_WideUInt) 0xffffffff)) {
	w >>= 32; rv += 32;
    }
    if (!(w & (Tcl_WideUInt) 0xffff)) {
	w >>= 16; rv += 16;
    }
    if (!(w & (Tcl_WideUInt) 0xff)) {
	w >>= 8; rv += 8;
    }
    if (!(w & (Tcl_WideUInt) 0xf)) {
	w >>= 4; rv += 4;
    }
    if (!(w & 0x3)) {
	w >>= 2; rv += 2;
    }
    if (!(w & 0x1)) {
	w >>= 1; ++rv;
    }
    *wPtr = w;
    return rv;
}

/*
 *-----------------------------------------------------------------------------0
 *
 * RequiredPrecision --
 *
 *	Determines the number of bits needed to hold an intger.
 *
 * Results:
 *	Returns the position of the most significant bit (0 - 63).
 *	Returns 0 if the number is zero.
 *
 *----------------------------------------------------------------------------
 */

static int
RequiredPrecision(Tcl_WideUInt w)
				/* Number to interrogate */
{
    int rv;
    unsigned long wi;

    if (w & ((Tcl_WideUInt) 0xffffffff << 32)) {
	wi = (unsigned long) (w >> 32); rv = 32;
    } else {
	wi = (unsigned long) w; rv = 0;
    }
    if (wi & 0xffff0000) {
	wi >>= 16; rv += 16;
    }
    if (wi & 0xff00) {
	wi >>= 8; rv += 8;
    }
    if (wi & 0xf0) {
	wi >>= 4; rv += 4;
    }
    if (wi & 0xc) {
	wi >>= 2; rv += 2;
    }
    if (wi & 0x2) {
	wi >>= 1; ++rv;
    }
    if (wi & 0x1) {
	++rv;
    }
    return rv;
}

/*
 *-----------------------------------------------------------------------------
 *
 * DoubleToExpAndSig --
 *
 *	Separates a 'double' into exponent and significand.
 *
 * Side effects:
 *	Stores the significand in '*significand' and the exponent in
 *	'*expon' so that dv == significand * 2.0**expon, and significand
 *	is odd.  Also stores the position of the leftmost 1-bit in 'significand'
 *	in 'bits'.
 *
 *-----------------------------------------------------------------------------
 */

inline static void
DoubleToExpAndSig(double dv,	/* Number to convert */

		  Tcl_WideUInt* significand,
				/* OUTPUT: Significand of the number */
		  int* expon,	/* OUTPUT: Exponent to multiply the number by */

		  int* bits)	/* OUTPUT: Number of significant bits */
{
    Double d;			/* Number being converted */
    Tcl_WideUInt z;		/* Significand under construction */
    int de;			/* Exponent of the number */
    int k;			/* Bit count */

    d.d = dv;


    /* Extract exponent and significand */


    de = (d.w.word0 & EXP_MASK) >> EXP_SHIFT;
    z = d.q & SIG_MASK;
    if (de != 0) {
	z |= HIDDEN_BIT;
	k = NormalizeRightward(&z);
	*bits = FP_PRECISION - k;
	*expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1);
    } else {
	k = NormalizeRightward(&z);
	*expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1) + 1;
	*bits = RequiredPrecision(z);
    }
    *significand = z;
}

/*
 *-----------------------------------------------------------------------------
 *
 * TakeAbsoluteValue --
 *
 *	Takes the absolute value of a 'double' including 0, Inf and NaN
 *
 * Side effects:
 *	The 'double' in *d is replaced with its absolute value. The
 *	signum is stored in 'sign': 1 for negative, 0 for nonnegative.
 *
 *-----------------------------------------------------------------------------
 */

inline static void

TakeAbsoluteValue(Double* d,	/* Number to replace with absolute value */
		  int* sign)	/* Place to put the signum */
{
    if (d->w.word0 & SIGN_BIT) {
	*sign = 1;
	d->w.word0 &= ~SIGN_BIT;
    } else {
	*sign = 0;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * FormatInfAndNaN --
 *
 *	Bailout for formatting infinities and Not-A-Number.
 *
 * Results:
 *	Returns one of the strings 'Infinity' and 'NaN'.

 *
 * Side effects:
 *	Stores 9999 in *decpt, and sets '*endPtr' to designate the
 *	terminating NUL byte of the string if 'endPtr' is not NULL.
 *
 * The string returned must be freed by the caller using 'ckfree'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
FormatInfAndNaN(Double* d,	/* Exceptional number to format */

		int* decpt,	/* Decimal point to set to a bogus value */
		char** endPtr)	/* Pointer to the end of the formatted data */
{
    char* retval;

    *decpt = 9999;
    if (!(d->w.word1) && !(d->w.word0 & HI_ORDER_SIG_MASK)) {
	retval = ckalloc(9);
	strcpy(retval, "Infinity");
	if (endPtr) {
	    *endPtr = retval + 8;
	}
    } else {
	retval = ckalloc(4);
	strcpy(retval, "NaN");
	if (endPtr) {
	    *endPtr = retval + 3;
	}
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * FormatZero --
 *
 *	Bailout to format a zero floating-point number.
 *
 * Results:
 *	Returns the constant string "0"
 *
 * Side effects:
 *	Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating
 *	the string in '*endPtr' if 'endPtr' is not NULL.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*

FormatZero(int* decpt,		/* Location of the decimal point */
	   char** endPtr)	/* Pointer to the end of the formatted data */
{
    char* retval = ckalloc(2);

    strcpy(retval, "0");
    if (endPtr) {
	*endPtr = retval+1;
    }
    *decpt = 0;
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ApproximateLog10 --
 *
 *	Computes a two-term Taylor series approximation to the common
 *	log of a number, and computes the number's binary log.
 *
 * Results:
 *	Return an approximation to floor(log10(bw*2**be)) that is either
 *	exact or 1 too high.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ApproximateLog10(Tcl_WideUInt bw,
				/* Integer significand of the number */
		 int be,	/* Power of two to scale bw */
		 int bbits)	/* Number of bits of precision in bw */
{
    int i;			/* Log base 2 of the number */
    int k;			/* Floor(Log base 10 of the number) */
    double ds;			/* Mantissa of the number */
    Double d2;

    /*
     * Compute i and d2 such that d = d2*2**i, and 1 < d2 < 2.
     * Compute an approximation to log10(d),
     *   log10(d) ~ log10(2) * i + log10(1.5)
     *            + (significand-1.5)/(1.5 * log(10))
     */

    d2.q = bw << (FP_PRECISION - bbits) & SIG_MASK;
    d2.w.word0 |= (EXPONENT_BIAS) << EXP_SHIFT;
    i = be + bbits - 1;
    ds = (d2.d - 1.5) * TWO_OVER_3LOG10
	+ LOG10_3HALVES_PLUS_FUDGE
	+ LOG10_2 * i;
    k = (int) ds;
    if (k > ds) {
	--k;
    }
    return k;
}

/*
 *-----------------------------------------------------------------------------
 *
 * BetterLog10 --
 *
 *	Improves the result of ApproximateLog10 for numbers in the range
 *	1 .. 10**(TEN_PMAX)-1
 *
 * Side effects:
 *	Sets k_check to 0 if the new result is known to be exact, and to
 *	1 if it may still be one too high.
 *
 * Results:
 *	Returns the improved approximation to log10(d)
 *
 *-----------------------------------------------------------------------------
 */

inline static int

BetterLog10(double d,		/* Original number to format */
	  int k,		/* Characteristic(Log base 10) of the number */

	  int* k_check)		/* Flag == 1 if k is inexact */
{
    /*
     * Performance hack. If k is in the range 0..TEN_PMAX, then we can
     * use a powers-of-ten table to check it.
     */

    if (k >= 0 && k <= TEN_PMAX) {
	if (d < tens[k]) {
	    k--;
	}
	*k_check = 0;
    } else {
	*k_check = 1;
    }
    return k;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ComputeScale --
 *
 *	Prepares to format a floating-point number as decimal.
 *
 * Parameters:
 *	floor(log10*x) is k (or possibly k-1).  floor(log2(x) is i.
 *	The significand of x requires bbits bits to represent.
 *
 * Results:
 *	Determines integers b2, b5, s2, s5 so that sig*2**b2*5**b5/2**s2*2**s5
 *	exactly represents the value of the x/10**k. This value will lie
 *	in the range [1 .. 10), and allows for computing successive digits
 *	by multiplying sig%10 by 10.
 *
 *-----------------------------------------------------------------------------
 */

inline static void

ComputeScale(int be,		/* Exponent part of number: d = bw * 2**be */
	     int k,		/* Characteristic of log10(number) */
	     int* b2,		/* OUTPUT: Power of 2 in the numerator */
	     int* b5,		/* OUTPUT: Power of 5 in the numerator */
	     int* s2,		/* OUTPUT: Power of 2 in the denominator */
	     int* s5)		/* OUTPUT: Power of 5 in the denominator */
{

    /*
     * Scale numerator and denominator powers of 2 so that the
     * input binary number is the ratio of integers
     */

    if (be <= 0) {
	*b2 = 0;
	*s2 = -be;
    } else {
	*b2 = be;
	*s2 = 0;
    }

    /*
     * Scale numerator and denominator so that the output decimal number
     * is the ratio of integers
     */

    if (k >= 0) {
	*b5 = 0;
	*s5 = k;
	*s2 += k;
    } else {
	*b2 -= k;
	*b5 = -k;
	*s5 = 0;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * SetPrecisionLimits --
 *
 *	Determines how many digits of significance should be computed
 *	(and, hence, how much memory need be allocated) for formatting a
 *	floating point number.
 *
 * Given that 'k' is floor(log10(x)):
 * if 'shortest' format is used, there will be at most 18 digits in the result.

 * if 'F' format is used, there will be at most 'ndigits' + k + 1 digits
 * if 'E' format is used, there will be exactly 'ndigits' digits.
 *
 * Side effects:
 *	Adjusts '*ndigitsPtr' to have a valid value.
 *	Stores the maximum memory allocation needed in *iPtr.
 *	Sets '*iLimPtr' to the limiting number of digits to convert if k
 *	has been guessed correctly, and '*iLim1Ptr' to the limiting number
 *	of digits to convert if k has been guessed to be one too high.

 *
 *-----------------------------------------------------------------------------
 */

inline static void
SetPrecisionLimits(int convType,
				/* Type of conversion:
				 *   TCL_DD_SHORTEST
				 *   TCL_DD_STEELE0
				 *   TCL_DD_E_FMT
				 *   TCL_DD_F_FMT */
		   int k,	/* Floor(log10(number to convert)) */
		   int* ndigitsPtr,
				/* IN/OUT: Number of digits requested
				 *         (Will be adjusted if needed) */
		   int* iPtr,	/* OUT: Maximum number of digits
				 *      to return */
		   int *iLimPtr,/* OUT: Number of digits of significance
				 *      if the bignum method is used.*/
		   int *iLim1Ptr)
				/* OUT: Number of digits of significance
				 *      if the quick method is used. */
{
    switch(convType) {
    case TCL_DD_SHORTEST0:
    case TCL_DD_STEELE0:
	*iLimPtr = *iLim1Ptr = -1;
	*iPtr = 18;
	*ndigitsPtr = 0;
	break;
    case TCL_DD_E_FORMAT:
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610

2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722

2723

2724

2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921

2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018

3019
3020
3021


3022
3023
3024
3025
3026


3027

3028
3029

3030

3031

3032

3033

3034
3035
3036

3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092

3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116

3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187

3188
3189
3190


3191
3192

3193

3194
3195

3196

3197

3198

3199

3200
3201
3202

3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242

3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294

3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331

3332

3333

3334
3335
3336

3337

3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394

3395
3396
3397


3398
3399
3400
3401
3402


3403

3404
3405

3406

3407

3408

3409

3410
3411
3412

3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
    default:
	*iPtr = -1;
	*iLimPtr = -1;
	*iLim1Ptr = -1;
	Tcl_Panic("impossible conversion type in TclDoubleDigits");
    }
}

/*
 *----------------------------------------------------------------------
 *
 * BumpUp --
 *
 *	Increases a string of digits ending in a series of nines to designate
 *	the next higher number.  xxxxb9999... -> xxxx(b+1)0000...
 *
 * Results:
 *	Returns a pointer to the end of the adjusted string.
 *
 * Side effects:
 *	In the case that the string consists solely of '999999', sets it to
 *	"1" and moves the decimal point (*kPtr) one place to the right.
 *
 *----------------------------------------------------------------------
 */


static inline char *
BumpUp(
    char *s,		    	/* Cursor pointing one past the end of the
				 * string. */
    char *retval,		/* Start of the string of digits. */
    int *kPtr)			/* Position of the decimal point. */
{
    while (*--s == '9') {
	if (s == retval) {
	    ++(*kPtr);
	    *s = '1';
	    return s+1;
	}
    }
    ++*s;
    ++s;
    return s;
}

/*
 *----------------------------------------------------------------------
 *
 * AdjustRange --
 *
 *	Rescales a 'double' in preparation for formatting it using the 'quick'
 *	double-to-string method.
 *
 * Results:
 *	Returns the precision that has been lost in the prescaling as a count
 *	of units in the least significant place.
 *
 *----------------------------------------------------------------------
 */

static inline int
AdjustRange(
    double *dPtr,		/* INOUT: Number to adjust. */
    int k)			/* IN: floor(log10(d)) */
{
    int ieps;			/* Number of roundoff errors that have
				 * accumulated. */
    double d = *dPtr;		/* Number to adjust. */
    double ds;
    int i, j, j1;

    ieps = 2;

    if (k > 0) {
	/*
	 * The number must be reduced to bring it into range.
	 */

	ds = tens[k & 0xF];
	j = k >> 4;
	if (j & BLETCH) {
	    j &= (BLETCH-1);
	    d /= bigtens[N_BIGTENS - 1];
	    ieps++;
	}
	i = 0;
	for (; j != 0; j>>=1) {
	    if (j & 1) {
		ds *= bigtens[i];
		++ieps;
	    }
	    ++i;
	}
	d /= ds;
    } else if ((j1 = -k) != 0) {
	/*
	 * The number must be increased to bring it into range.
	 */

	d *= tens[j1 & 0xF];
	i = 0;
	for (j = j1>>4; j; j>>=1) {
	    if (j & 1) {
		ieps++;
		d *= bigtens[i];
	    }
	    ++i;
	}
    }

    *dPtr = d;
    return ieps;
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningQuickFormat --
 *
 *	Returns a 'quick' format of a double precision number to a string of
 *	digits, preferring a shorter string of digits if the shorter string is
 *	still within 1/2 ulp of the number.
 *
 * Results:
 *	Returns the string of digits. Returns NULL if the 'quick' method fails
 *	and the bignum method must be used.
 *
 * Side effects:
 *	Stores the position of the decimal point at '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */

    double eps,			/* Estimated roundoff error. */

    char *retval,		/* Buffer to receive the digit string. */

    int *kPtr)			/* Pointer to stash the position of the
				 * decimal point. */
{
    char *s = retval;		/* Cursor in the return value. */
    int digit;			/* Current digit. */
    int i;

    eps = 0.5 / tens[ilim-1] - eps;
    i = 0;
    for (;;) {
	/*
	 * Convert a digit.
	 */

	digit = (int) d;
	d -= digit;
	*s++ = '0' + digit;

	/*
	 * Truncate the conversion if the string of digits is within 1/2 ulp
	 * of the actual value.
	 */

	if (d < eps) {
	    *kPtr = k;
	    return s;
	}
	if ((1. - d) < eps) {
	    *kPtr = k;
	    return BumpUp(s, retval, kPtr);
	}

	/*
	 * Bail out if the conversion fails to converge to a sufficiently
	 * precise value.
	 */

	if (++i >= ilim) {
	    return NULL;
	}

	/*
	 * Bring the next digit to the integer part.
	 */

	eps *= 10;
	d *= 10.0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * StrictQuickFormat --
 *
 *	Convert a double precision number of a string of a precise number of
 *	digits, using the 'quick' double precision method.
 *
 * Results:
 *	Returns the digit string, or NULL if the bignum method must be used to
 *	do the formatting.
 *
 * Side effects:
 *	Stores the position of the decimal point in '*kPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictQuickFormat(
    double d,			/* Number to convert. */
    int k,			/* floor(log10(d)) */
    int ilim,			/* Number of significant digits to return. */
    double eps,			/* Estimated roundoff error. */
    char *retval,		/* Start of the digit string. */
    int *kPtr)			/* Pointer to stash the position of the
				 * decimal point. */
{
    char *s = retval;		/* Cursor in the return value. */
    int digit;			/* Current digit of the answer. */
    int i;

    eps *= tens[ilim-1];
    i = 1;
    for (;;) {
	/*
	 * Extract a digit.
	 */

	digit = (int) d;
	d -= digit;
	if (d == 0.0) {
	    ilim = i;
	}
	*s++ = '0' + digit;

	/*
	 * When the given digit count is reached, handle trailing strings of 0
	 * and 9.
	 */

	if (i == ilim) {
	    if (d > 0.5 + eps) {
		*kPtr = k;
		return BumpUp(s, retval, kPtr);
	    } else if (d < 0.5 - eps) {
		while (*--s == '0') {
		    /* do nothing */
		}
		s++;
		*kPtr = k;
		return s;
	    } else {
		return NULL;
	    }
	}

	/*
	 * Advance to the next digit.
	 */

	++i;
	d *= 10.0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * QuickConversion --
 *
 *	Converts a floating point number the 'quick' way, when only a limited
 *	number of digits is required and floating point arithmetic can
 *	therefore be used for the intermediate results.
 *
 * Results:
 *	Returns the converted string, or NULL if the bignum method must be
 *	used.
 *
 *----------------------------------------------------------------------
 */

static inline char *
QuickConversion(
    double e,			/* Number to format. */
    int k,			/* floor(log10(d)), approximately. */
    int k_check,		/* 0 if k is exact, 1 if it may be too high */
    int flags,			/* Flags passed to dtoa:
				 *    TCL_DD_SHORTEN_FLAG */
    int len,			/* Length of the return value. */
    int ilim,			/* Number of digits to store. */
    int ilim1,			/* Number of digits to store if we misguessed
				 * k. */
    int *decpt,			/* OUTPUT: Location of the decimal point. */
    char **endPtr)		/* OUTPUT: Pointer to the terminal null
				 * byte. */
{
    int ieps;			/* Number of 1-ulp roundoff errors that have
				 * accumulated in the calculation. */
    Double eps;			/* Estimated roundoff error. */
    char *retval;		/* Returned string. */
    char *end;			/* Pointer to the terminal null byte in the
				 * returned string. */
    volatile double d;		/* Workaround for a bug in mingw gcc 3.4.5 */

    /*
     * Bring d into the range [1 .. 10).
     */

    ieps = AdjustRange(&e, k);
    d = e;

    /*
     * If the guessed value of k didn't get d into range, adjust it by one. If
     * that leaves us outside the range in which quick format is accurate,
     * bail out.
     */

    if (k_check && d < 1. && ilim > 0) {
	if (ilim1 < 0) {
	    return NULL;
	}
	ilim = ilim1;
	--k;
	d = d * 10.0;
	++ieps;
    }

    /*
     * Compute estimated roundoff error.
     */

    eps.d = ieps * d + 7.;
    eps.w.word0 -= (FP_PRECISION-1) << EXP_SHIFT;

    /*
     * Handle the peculiar case where the result has no significant digits.

     */

    retval = ckalloc(len + 1);
    if (ilim == 0) {
	d = d - 5.;
	if (d > eps.d) {
	    *retval = '1';
	    *decpt = k;
	    return retval;
	} else if (d < -eps.d) {
	    *decpt = k;
	    return retval;
	} else {
	    ckfree(retval);
	    return NULL;
	}
    }

    /*
     * Format the digit string.
     */

    if (flags & TCL_DD_SHORTEN_FLAG) {
	end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt);
    } else {
	end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt);
    }
    if (end == NULL) {
	ckfree(retval);
	return NULL;
    }
    *end = '\0';
    if (endPtr != NULL) {
	*endPtr = end;
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * CastOutPowersOf2 --
 *
 *	Adjust the factors 'b2', 'm2', and 's2' to cast out common powers of 2
 *	from numerator and denominator in preparation for the 'bignum' method
 *	of floating point conversion.
 *
 *----------------------------------------------------------------------
 */

static inline void
CastOutPowersOf2(
    int *b2,			/* Power of 2 to multiply the significand. */
    int *m2,			/* Power of 2 to multiply 1/2 ulp. */
    int *s2)			/* Power of 2 to multiply the common
				 * denominator. */
{
    int i;

    if (*m2 > 0 && *s2 > 0) {	/* Find the smallest power of 2 in the
				 * numerator. */
	if (*m2 < *s2) {	/* Find the lowest common denominator. */
	    i = *m2;
	} else {
	    i = *s2;
	}
	*b2 -= i;		/* Reduce to lowest terms. */
	*m2 -= i;
	*s2 -= i;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningInt64Conversion --
 *
 *	Converts a double-precision number to the shortest string of digits
 *	that reconverts exactly to the given number, or to 'ilim' digits if
 *	that will yield a shorter result. The numerator and denominator in
 *	David Gay's conversion algorithm are known to fit in Tcl_WideUInt,
 *	giving considerably faster arithmetic than mp_int's.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly allocated
 *	memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningInt64Conversion(
    Double *dPtr,		/* Original number to convert. */

    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */


    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
    int m2plus, int m2minus, int m5,
				/* Scale factors for 1/2 ulp in the numerator
				 * (will be different if bw == 1. */


    int s2, int s5,		/* Scale factors for the denominator. */

    int k,			/* Number of output digits before the decimal
				 * point. */

    int len,			/* Number of digits to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Position of the terminal '\0' at
				 *	   the end of the returned string. */
{

    char *retval = ckalloc(len + 1);
				/* Output buffer. */
    Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
				/* Numerator of the fraction being
				 * converted. */
    Tcl_WideUInt S = wuipow5[s5] << s2;
				/* Denominator of the fraction being
				 * converted. */
    Tcl_WideUInt mplus, mminus;	/* Ranges for testing whether the result is
				 * within roundoff of being exact. */
    int digit;			/* Current output digit. */
    char *s = retval;		/* Cursor in the output buffer. */
    int i;			/* Current position in the output buffer. */

    /*
     * Adjust if the logarithm was guessed wrong.
     */

    if (b < S) {
	b = 10 * b;
	++m2plus; ++m2minus; ++m5;
	ilim = ilim1;
	--k;
    }

    /*
     * Compute roundoff ranges.
     */

    mplus = wuipow5[m5] << m2plus;
    mminus = wuipow5[m5] << m2minus;

    /*
     * Loop through the digits.
     */

    i = 1;
    for (;;) {
	digit = (int)(b / S);
	if (digit > 10) {
	    Tcl_Panic("wrong digit!");
	}
	b = b % S;

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 */

	if (b < mplus || (b == mplus
		&& convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) {

	    /*
	     * Make sure we shouldn't be rounding *up* instead, in case the
	     * next number above is closer.
	     */


	    if (2 * b > S || (2 * b == S && (digit & 1) != 0)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }

	    /*
	     * Stash the current digit.
	     */

	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does one plus the current digit put us within roundoff of the
	 * number?
	 */

	if (b > S - mminus || (b == S - mminus
		&& convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) {

	    if (digit == 9) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    ++digit;
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {

	    if (2*b > S || (2*b == S && (digit & 1) != 0)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}

	/*
	 * Advance to the next digit.
	 */

	b = 10 * b;
	mplus = 10 * mplus;
	mminus = 10 * mminus;
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * StrictInt64Conversion --
 *
 *	Converts a double-precision number to a fixed-length string of 'ilim'
 *	digits that reconverts exactly to the given number.  ('ilim' should be
 *	replaced with 'ilim1' in the case where log10(d) has been
 *	overestimated).  The numerator and denominator in David Gay's
 *	conversion algorithm are known to fit in Tcl_WideUInt, giving
 *	considerably faster arithmetic than mp_int's.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly allocated
 *	memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictInt64Conversion(
    Double *dPtr,		/* Original number to convert. */

    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */


    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */

    int s2, int s5,		/* Scale factors for the denominator. */

    int k,			/* Number of output digits before the decimal
				 * point. */

    int len,			/* Number of digits to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Position of the terminal '\0' at
				 *	   the end of the returned string. */
{

    char *retval = ckalloc(len + 1);
				/* Output buffer. */
    Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
				/* Numerator of the fraction being
				 * converted. */
    Tcl_WideUInt S = wuipow5[s5] << s2;
				/* Denominator of the fraction being
				 * converted. */
    int digit;			/* Current output digit. */
    char *s = retval;		/* Cursor in the output buffer. */
    int i;			/* Current position in the output buffer. */

    /*
     * Adjust if the logarithm was guessed wrong.
     */

    if (b < S) {
	b = 10 * b;
	ilim = ilim1;
	--k;
    }

    /*
     * Loop through the digits.
     */

    i = 1;
    for (;;) {
	digit = (int)(b / S);
	if (digit > 10) {
	    Tcl_Panic("wrong digit!");
	}
	b = b % S;

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {

	    if (2*b > S || (2*b == S && (digit & 1) != 0)) {
		s = BumpUp(s, retval, &k);
	    } else {
		while (*--s == '0') {
		    /* do nothing */
		}
		++s;
	    }
	    break;
	}

	/*
	 * Advance to the next digit.
	 */

	b = 10 * b;
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUpPowD --
 *
 *	Test whether bankers' rounding should round a digit up. Assumption is
 *	made that the denominator of the fraction being tested is a power of
 *	2**MP_DIGIT_BIT.
 *
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction is
 *	exactly 1/2 and the digit is odd.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpPowD(
    mp_int *b,			/* Numerator of the fraction. */
    int sd,			/* Denominator is 2**(sd*MP_DIGIT_BIT). */

    int isodd)			/* 1 if the digit is odd, 0 if even. */
{
    int i;
    static const mp_digit topbit = ((mp_digit)1) << (MP_DIGIT_BIT - 1);

    if (b->used < sd || (b->dp[sd-1] & topbit) == 0) {
	return 0;
    }
    if (b->dp[sd-1] != topbit) {
	return 1;
    }
    for (i = sd-2; i >= 0; --i) {
	if (b->dp[i] != 0) {
	    return 1;
	}
    }
    return isodd;
}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNextPowD --
 *
 *	Tests whether bankers' rounding will round down in the "denominator is
 *	a power of 2**MP_DIGIT" case.
 *
 * Results:
 *	Returns 1 if the rounding will be performed - which increases the
 *	digit by one - and 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpToNextPowD(
    mp_int *b,			/* Numerator of the fraction. */

    mp_int *m,			/* Numerator of the rounding tolerance. */

    int sd,			/* Common denominator is 2**(sd*MP_DIGIT_BIT). */

    int convType,		/* Conversion type: STEELE defeats
				 * round-to-even (not sure why one wants to do
				 * this; I copied it from Gay). FIXME */

    int isodd,			/* 1 if the integer significand is odd. */

    mp_int *temp)		/* Work area for the calculation. */
{
    int i;

    /*
     * Compare B and S-m - which is the same as comparing B+m and S - which we
     * do by computing b+m and doing a bitwhack compare against
     * 2**(MP_DIGIT_BIT*sd)
     */

    mp_add(b, m, temp);
    if (temp->used <= sd) {	/* Too few digits to be > s */
	return 0;
    }
    if (temp->used > sd+1 || temp->dp[sd] > 1) {
				/* >= 2s */
	return 1;
    }
    for (i = sd-1; i >= 0; --i) {
				/* Check for ==s */
	if (temp->dp[i] != 0) {	/* > s */
	    return 1;
	}
    }
    if (convType == TCL_DD_STEELE0) {
				/* Biased rounding. */
	return 0;
    }
    return isodd;
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningBignumConversionPowD --
 *
 *	Converts a double-precision number to the shortest string of digits
 *	that reconverts exactly to the given number, or to 'ilim' digits if
 *	that will yield a shorter result. The denominator in David Gay's
 *	conversion algorithm is known to be a power of 2**MP_DIGIT_BIT, and hence
 *	the division in the main loop may be replaced by a digit shift and
 *	mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly allocated
 *	memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */

    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */


    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */
    int m2plus, int m2minus, int m5,
				/* Scale factors for 1/2 ulp in the numerator
				 * (will be different if bw == 1). */


    int sd,			/* Scale factor for the denominator. */

    int k,			/* Number of output digits before the decimal
				 * point. */

    int len,			/* Number of digits to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Position of the terminal '\0' at
				 *	   the end of the returned string. */
{

    char *retval = ckalloc(len + 1);
				/* Output buffer. */
    mp_int b;			/* Numerator of the fraction being
				 * converted. */
    mp_int mplus, mminus;	/* Bounds for roundoff. */
    mp_digit digit;		/* Current output digit. */
    char *s = retval;		/* Cursor in the output buffer. */
    int i;			/* Index in the output buffer. */
    mp_int temp;
    int r1;

    /*
     * b = bw * 2**b2 * 5**b5
     * mminus = 5**m5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    mp_init_set(&mminus, 1);
    MulPow5(&b, b5, &b);
    mp_mul_2d(&b, b2, &b);

    /*
     * Adjust if the logarithm was guessed wrong.
     */

    if (b.used <= sd) {
	mp_mul_d(&b, 10, &b);
	++m2plus; ++m2minus; ++m5;
	ilim = ilim1;
	--k;
    }







|

|



|
|





|
|

|


>
|
<
|
|
|
|














|



|
|


|
|

|


|
|
<
|


|
|









<
|

















|

<
|















|



|
|
|


|
|




|


|
|
<
|
|
>
|
>
|
>
|
|

|
|





<
|
<






|
|













|
















|



|
|


|
|




|


|
|
<
|
|
|
|
|
|

|
|





<
|
<
<








|
|

<
















<
|
<
<






|








|
|

|


|
|
<
|
|
|

|
|
|
|
|
|
<


|
|
|
|
|



|

<




|
|
|

<






|




|

<




|
>

<


|













<
|
<


















|



|
|
|

|


|
<
|
|
|
|


<

|
|




|






|



|
|
|
|
|


|
|


|
|

|


|
|
|
>
|
|
|
>
>
|
|
|
|
|
>
>
|
>
|
|
>
|
>
|
>
|
>
|
>
|
|

>
|
|

|
<


|
|
|
|
|
|

<
|
<








<
|
<




<
|
<













|
|
|
>

|
|

|
>
|








<
|
<









|
|
|
>













<


>
|





<
|
<











<









|



|
|
|
|
|
|


|
|


|
|

|


|
|
|
>
|
|
|
>
>
|
|
>
|
>
|
|
>
|
>
|
>
|
>
|
>
|
|

>
|
|

|
<


|
|
|
|

<
|
<







<
|
<












<


>
|










<
|
<









<









|



|
|
|


|
|

|


|
|
|
|
>
|


|
<















|



|
|





|


|
|
|
>
|
>
|
>
|
|
|
>
|
>
|




|
|
|

<

|







|





|






|



|
|
|
|
|
|


|
|


|
|

|


|
|
|
>
|
|
|
>
>
|
|
|
|
|
>
>
|
>
|
|
>
|
>
|
>
|
>
|
>
|
|

>
|
|
|
<
|
|
|
|









|



<
|
<







2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551

2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568

2569

2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640

2641


2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652

2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668

2669


2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692

2693
2694
2695
2696
2697
2698
2699
2700
2701
2702

2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714

2715
2716
2717
2718
2719
2720
2721
2722

2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735

2736
2737
2738
2739
2740
2741
2742

2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758

2759

2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789

2790
2791
2792
2793
2794
2795

2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875
2876

2877

2878
2879
2880
2881
2882
2883
2884
2885

2886

2887
2888
2889
2890

2891

2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923

2924

2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2958
2959

2960

2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035

3036
3037
3038
3039
3040
3041
3042

3043

3044
3045
3046
3047
3048
3049
3050

3051

3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077

3078

3079
3080
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120

3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252

3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269

3270

3271
3272
3273
3274
3275
3276
3277
    default:
	*iPtr = -1;
	*iLimPtr = -1;
	*iLim1Ptr = -1;
	Tcl_Panic("impossible conversion type in TclDoubleDigits");
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * BumpUp --
 *
 *	Increases a string of digits ending in a series of nines to
 *	designate the next higher number.  xxxxb9999... -> xxxx(b+1)0000...
 *
 * Results:
 *	Returns a pointer to the end of the adjusted string.
 *
 * Side effects:
 *	In the case that the string consists solely of '999999', sets it
 *	to "1" and moves the decimal point (*kPtr) one place to the right.
 *
 *-----------------------------------------------------------------------------
 */


inline static char*

BumpUp(char* s,		    	/* Cursor pointing one past the end of the
				 * string */
       char* retval,		/* Start of the string of digits */
       int* kPtr)		/* Position of the decimal point */
{
    while (*--s == '9') {
	if (s == retval) {
	    ++(*kPtr);
	    *s = '1';
	    return s+1;
	}
    }
    ++*s;
    ++s;
    return s;
}

/*
 *-----------------------------------------------------------------------------
 *
 * AdjustRange --
 *
 *	Rescales a 'double' in preparation for formatting it using the
 *	'quick' double-to-string method.
 *
 * Results:
 *	Returns the precision that has been lost in the prescaling as
 *	a count of units in the least significant place.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
AdjustRange(double* dPtr,	/* INOUT: Number to adjust */

	    int k)		/* IN: floor(log10(d)) */
{
    int ieps;			/* Number of roundoff errors that have
				 * accumulated */
    double d = *dPtr;		/* Number to adjust */
    double ds;
    int i, j, j1;

    ieps = 2;

    if (k > 0) {
	/*
	 * The number must be reduced to bring it into range.
	 */

	ds = tens[k & 0xf];
	j = k >> 4;
	if (j & BLETCH) {
	    j &= (BLETCH-1);
	    d /= bigtens[N_BIGTENS - 1];
	    ieps++;
	}
	i = 0;
	for (; j != 0; j>>=1) {
	    if (j & 1) {
		ds *= bigtens[i];
		++ieps;
	    }
	    ++i;
	}
	d /= ds;
    } else if ((j1 = -k) != 0) {
	/*
	 * The number must be increased to bring it into range
	 */

	d *= tens[j1 & 0xf];
	i = 0;
	for (j = j1>>4; j; j>>=1) {
	    if (j & 1) {
		ieps++;
		d *= bigtens[i];
	    }
	    ++i;
	}
    }

    *dPtr = d;
    return ieps;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShorteningQuickFormat --
 *
 *	Returns a 'quick' format of a double precision number to a string
 *	of digits, preferring a shorter string of digits if the shorter
 *	string is still within 1/2 ulp of the number.
 *
 * Results:
 *	Returns the string of digits. Returns NULL if the 'quick' method
 *	fails and the bignum method must be used.
 *
 * Side effects:
 *	Stores the position of the decimal point at '*kPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
ShorteningQuickFormat(double d,	/* Number to convert */

		      int k,	/* floor(log10(d)) */
		      int ilim,	/* Number of significant digits to return */
		      double eps,
		      		/* Estimated roundoff error */
		      char* retval,
		      		/* Buffer to receive the digit string */
		      int* kPtr)
				/* Pointer to stash the position of
				 * the decimal point */
{
    char* s = retval;		/* Cursor in the return value */
    int digit;			/* Current digit */
    int i;

    eps = 0.5 / tens[ilim-1] - eps;
    i = 0;
    for (;;) {

	/* Convert a digit */


	digit = (int) d;
	d -= digit;
	*s++ = '0' + digit;

	/*
	 * Truncate the conversion if the string of digits is within
	 * 1/2 ulp of the actual value.
	 */

	if (d < eps) {
	    *kPtr = k;
	    return s;
	}
	if ((1. - d) < eps) {
	    *kPtr = k;
	    return BumpUp(s, retval, kPtr);
	}

	/*
	 * Bail out if the conversion fails to converge to a sufficiently
	 * precise value
	 */

	if (++i >= ilim) {
	    return NULL;
	}

	/*
	 * Bring the next digit to the integer part.
	 */

	eps *= 10;
	d *= 10.0;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * StrictQuickFormat --
 *
 *	Convert a double precision number of a string of a precise number
 *	of digits, using the 'quick' double precision method.
 *
 * Results:
 *	Returns the digit string, or NULL if the bignum method must be
 *	used to do the formatting.
 *
 * Side effects:
 *	Stores the position of the decimal point in '*kPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
StrictQuickFormat(double d,	/* Number to convert */

		  int k,	/* floor(log10(d)) */
		  int ilim,	/* Number of significant digits to return */
		  double eps,	/* Estimated roundoff error */
		  char* retval,	/* Start of the digit string */
		  int* kPtr)	/* Pointer to stash the position of
				 * the decimal point */
{
    char* s = retval;		/* Cursor in the return value */
    int digit;			/* Current digit of the answer */
    int i;

    eps *= tens[ilim-1];
    i = 1;
    for (;;) {

	/* Extract a digit */


	digit = (int) d;
	d -= digit;
	if (d == 0.0) {
	    ilim = i;
	}
	*s++ = '0' + digit;

	/*
	 * When the given digit count is reached, handle trailing strings
	 * of 0 and 9.
	 */

	if (i == ilim) {
	    if (d > 0.5 + eps) {
		*kPtr = k;
		return BumpUp(s, retval, kPtr);
	    } else if (d < 0.5 - eps) {
		while (*--s == '0') {
		    /* do nothing */
		}
		s++;
		*kPtr = k;
		return s;
	    } else {
		return NULL;
	    }
	}


	/* Advance to the next digit */


	++i;
	d *= 10.0;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * QuickConversion --
 *
 *	Converts a floating point number the 'quick' way, when only a limited
 *	number of digits is required and floating point arithmetic can
 *	therefore be used for the intermediate results.
 *
 * Results:
 *	Returns the converted string, or NULL if the bignum method must
 *	be used.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
QuickConversion(double e,	/* Number to format */

		int k,		/* floor(log10(d)), approximately */
		int k_check,	/* 0 if k is exact, 1 if it may be too high */
		int flags,	/* Flags passed to dtoa:
				 *    TCL_DD_SHORTEN_FLAG */
		int len,	/* Length of the return value */
		int ilim,	/* Number of digits to store */
		int ilim1,	/* Number of digits to store if we
				 * musguessed k */
		int* decpt,	/* OUTPUT: Location of the decimal point */
		char** endPtr)	/* OUTPUT: Pointer to the terminal null byte */

{
    int ieps;			/* Number of 1-ulp roundoff errors that have
				 * accumulated in the calculation*/
    Double eps;			/* Estimated roundoff error */
    char* retval;		/* Returned string */
    char* end;			/* Pointer to the terminal null byte in the
				 * returned string */
    volatile double d;		/* Workaround for a bug in mingw gcc 3.4.5 */

    /*
     * Bring d into the range [1 .. 10)
     */

    ieps = AdjustRange(&e, k);
    d = e;

    /*
     * If the guessed value of k didn't get d into range, adjust it
     * by one. If that leaves us outside the range in which quick format
     * is accurate, bail out.
     */

    if (k_check && d < 1. && ilim > 0) {
	if (ilim1 < 0) {
	    return NULL;
	}
	ilim = ilim1;
	--k;
	d *= 10.0;
	++ieps;
    }

    /*
     * Compute estimated roundoff error
     */

    eps.d = ieps * d + 7.;
    eps.w.word0 -= (FP_PRECISION-1) << EXP_SHIFT;

    /*
     * Handle the peculiar case where the result has no significant
     * digits.
     */

    retval = ckalloc(len + 1);
    if (ilim == 0) {
	d -= 5.;
	if (d > eps.d) {
	    *retval = '1';
	    *decpt = k;
	    return retval;
	} else if (d < -eps.d) {
	    *decpt = k;
	    return retval;
	} else {
	    ckfree(retval);
	    return NULL;
	}
    }


    /* Format the digit string */


    if (flags & TCL_DD_SHORTEN_FLAG) {
	end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt);
    } else {
	end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt);
    }
    if (end == NULL) {
	ckfree(retval);
	return NULL;
    }
    *end = '\0';
    if (endPtr != NULL) {
	*endPtr = end;
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * CastOutPowersOf2 --
 *
 *	Adjust the factors 'b2', 'm2', and 's2' to cast out common powers
 *	of 2 from numerator and denominator in preparation for the 'bignum'
 *	method of floating point conversion.
 *
 *-----------------------------------------------------------------------------
 */

inline static void

CastOutPowersOf2(int* b2,	/* Power of 2 to multiply the significand  */
		 int* m2,	/* Power of 2 to multiply 1/2 ulp  */
		 int* s2)	/* Power of 2 to multiply the common
				 * denominator */
{
    int i;

    if (*m2 > 0 && *s2 > 0) {	/* Find the smallest power of 2 in the
				 * numerator */
        if (*m2 < *s2) {	/* Find the lowest common denominatorr */
	    i = *m2;
	} else {
	    i = *s2;
	}
	*b2 -= i;		/* Reduce to lowest terms */
	*m2 -= i;
	*s2 -= i;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShorteningInt64Conversion --
 *
 *	Converts a double-precision number to the shortest string of
 *	digits that reconverts exactly to the given number, or to
 *	'ilim' digits if that will yield a shorter result. The numerator and
 *	denominator in David Gay's conversion algorithm are known to fit
 *	in Tcl_WideUInt, giving considerably faster arithmetic than mp_int's.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the
 *      location of the terminal null byte in '*endPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
ShorteningInt64Conversion(Double* dPtr,
				/* Original number to convert */
			  int convType,
				/* Type of conversion (shortest, Steele,
				   E format, F format) */
			  Tcl_WideUInt bw,
				/* Integer significand */
			  int b2, int b5,
				/* Scale factor for the significand
				 * in the numerator */
			  int m2plus, int m2minus, int m5,
				/* Scale factors for 1/2 ulp in
				 * the numerator (will be different if
				 * bw == 1 */
			  int s2, int s5,
				/* Scale factors for the denominator */
			  int k,
				/* Number of output digits before the decimal
				 * point */
			  int len,
				/* Number of digits to allocate */
			  int ilim,
				/* Number of digits to convert if b >= s */
			  int ilim1,
				/* Number of digits to convert if b < s */
			  int* decpt,
				/* OUTPUT: Position of the decimal point */
			  char** endPtr)
				/* OUTPUT: Position of the terminal '\0'
				 *         at the end of the returned string */
{

    char* retval = ckalloc(len + 1);
				/* Output buffer */
    Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
				/* Numerator of the fraction being converted */

    Tcl_WideUInt S = wuipow5[s5] << s2;
				/* Denominator of the fraction being
				 * converted */
    Tcl_WideUInt mplus, mminus;	/* Ranges for testing whether the result
				 * is within roundoff of being exact */
    int digit;			/* Current output digit */
    char* s = retval;		/* Cursor in the output buffer */
    int i;			/* Current position in the output buffer */


    /* Adjust if the logarithm was guessed wrong */


    if (b < S) {
	b = 10 * b;
	++m2plus; ++m2minus; ++m5;
	ilim = ilim1;
	--k;
    }


    /* Compute roundoff ranges */


    mplus = wuipow5[m5] << m2plus;
    mminus = wuipow5[m5] << m2minus;


    /* Loop through the digits */


    i = 1;
    for (;;) {
	digit = (int)(b / S);
	if (digit > 10) {
	    Tcl_Panic("wrong digit!");
	}
	b = b % S;

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 */
	if (b < mplus
	    || (b == mplus
		&& convType != TCL_DD_STEELE0
		&& (dPtr->w.word1 & 1) == 0)) {
	    /*
	     * Make sure we shouldn't be rounding *up* instead,
	     * in case the next number above is closer
	     */
	    if (2 * b > S
		|| (2 * b == S
		    && (digit & 1) != 0)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }


	    /* Stash the current digit */


	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does one plus the current digit put us within roundoff of the
	 * number?
	 */
	if (b > S - mminus
	    || (b == S - mminus
		&& convType != TCL_DD_STEELE0
		&& (dPtr->w.word1 & 1) == 0)) {
	    if (digit == 9) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    ++digit;
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (2*b > S
		|| (2*b == S && (digit & 1) != 0)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}


	/* Advance to the next digit */


	b = 10 * b;
	mplus = 10 * mplus;
	mminus = 10 * mminus;
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * StrictInt64Conversion --
 *
 *	Converts a double-precision number to a fixed-length string of
 *	'ilim' digits that reconverts exactly to the given number.
 *	('ilim' should be replaced with 'ilim1' in the case where
 *	log10(d) has been overestimated).  The numerator and
 *	denominator in David Gay's conversion algorithm are known to fit
 *	in Tcl_WideUInt, giving considerably faster arithmetic than mp_int's.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the
 *      location of the terminal null byte in '*endPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
StrictInt64Conversion(Double* dPtr,
				/* Original number to convert */
		      int convType,
				/* Type of conversion (shortest, Steele,
				   E format, F format) */
		      Tcl_WideUInt bw,
				/* Integer significand */
		      int b2, int b5,
				/* Scale factor for the significand
				 * in the numerator */
		      int s2, int s5,
				/* Scale factors for the denominator */
		      int k,
				/* Number of output digits before the decimal
				 * point */
		      int len,
				/* Number of digits to allocate */
		      int ilim,
				/* Number of digits to convert if b >= s */
		      int ilim1,
				/* Number of digits to convert if b < s */
		      int* decpt,
				/* OUTPUT: Position of the decimal point */
		      char** endPtr)
				/* OUTPUT: Position of the terminal '\0'
				 *         at the end of the returned string */
{

    char* retval = ckalloc(len + 1);
				/* Output buffer */
    Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
				/* Numerator of the fraction being converted */

    Tcl_WideUInt S = wuipow5[s5] << s2;
				/* Denominator of the fraction being
				 * converted */
    int digit;			/* Current output digit */
    char* s = retval;		/* Cursor in the output buffer */
    int i;			/* Current position in the output buffer */


    /* Adjust if the logarithm was guessed wrong */


    if (b < S) {
	b = 10 * b;
	ilim = ilim1;
	--k;
    }


    /* Loop through the digits */


    i = 1;
    for (;;) {
	digit = (int)(b / S);
	if (digit > 10) {
	    Tcl_Panic("wrong digit!");
	}
	b = b % S;

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (2*b > S
		|| (2*b == S && (digit & 1) != 0)) {
		s = BumpUp(s, retval, &k);
	    } else {
		while (*--s == '0') {
		    /* do nothing */
		}
		++s;
	    }
	    break;
	}


	/* Advance to the next digit */


	b = 10 * b;
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUpPowD --
 *
 *	Test whether bankers' rounding should round a digit up. Assumption
 *	is made that the denominator of the fraction being tested is
 *	a power of 2**DIGIT_BIT.
 *
 * Results:
 *	Returns 1 iff the fraction is more than 1/2, or if the fraction
 *	is exactly 1/2 and the digit is odd.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpPowD(mp_int* b,
				/* Numerator of the fraction */
			int sd,	/* Denominator is 2**(sd*DIGIT_BIT) */
			int isodd)
				/* 1 if the digit is odd, 0 if even */
{
    int i;
    static const mp_digit topbit = (1<<(DIGIT_BIT-1));

    if (b->used < sd || (b->dp[sd-1] & topbit) == 0) {
	return 0;
    }
    if (b->dp[sd-1] != topbit) {
	return 1;
    }
    for (i = sd-2; i >= 0; --i) {
	if (b->dp[i] != 0) {
	    return 1;
	}
    }
    return isodd;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNextPowD --
 *
 *	Tests whether bankers' rounding will round down in the
 *	"denominator is a power of 2**MP_DIGIT" case.
 *
 * Results:
 *	Returns 1 if the rounding will be performed - which increases the
 *	digit by one - and 0 otherwise.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpToNextPowD(mp_int* b,
				/* Numerator of the fraction */
			      mp_int* m,
				/* Numerator of the rounding tolerance */
			      int sd,
				/* Common denominator is 2**(sd*DIGIT_BIT) */
			      int convType,
				/* Conversion type: STEELE defeats
				 * round-to-even (Not sure why one wants to
				 * do this; I copied it from Gay) FIXME */
			      int isodd,
				/* 1 if the integer significand is odd */
			      mp_int* temp)
				/* Work area for the calculation */
{
    int i;

    /*
     * Compare B and S-m -- which is the same as comparing B+m and S --
     * which we do by computing b+m and doing a bitwhack compare against
     * 2**(DIGIT_BIT*sd)
     */

    mp_add(b, m, temp);
    if (temp->used <= sd) {	/* too few digits to be > S */
	return 0;
    }
    if (temp->used > sd+1 || temp->dp[sd] > 1) {
				/* >= 2s */
	return 1;
    }
    for (i = sd-1; i >= 0; --i) {
				/* check for ==s */
	if (temp->dp[i] != 0) {	/* > s */
	    return 1;
	}
    }
    if (convType == TCL_DD_STEELE0) {
				/* biased rounding */
	return 0;
    }
    return isodd;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShorteningBignumConversionPowD --
 *
 *	Converts a double-precision number to the shortest string of
 *	digits that reconverts exactly to the given number, or to
 *	'ilim' digits if that will yield a shorter result. The denominator
 *	in David Gay's conversion algorithm is known to be a power of
 *	2**DIGIT_BIT, and hence the division in the main loop may be replaced
 *	by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the
 *      location of the terminal null byte in '*endPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
ShorteningBignumConversionPowD(Double* dPtr,
				/* Original number to convert */
			       int convType,
				/* Type of conversion (shortest, Steele,
				   E format, F format) */
			       Tcl_WideUInt bw,
				/* Integer significand */
			       int b2, int b5,
				/* Scale factor for the significand
				 * in the numerator */
			       int m2plus, int m2minus, int m5,
				/* Scale factors for 1/2 ulp in
				 * the numerator (will be different if
				 * bw == 1 */
			       int sd,
				/* Scale factor for the denominator */
			       int k,
				/* Number of output digits before the decimal
				 * point */
			       int len,
				/* Number of digits to allocate */
			       int ilim,
				/* Number of digits to convert if b >= s */
			       int ilim1,
				/* Number of digits to convert if b < s */
			       int* decpt,
				/* OUTPUT: Position of the decimal point */
			       char** endPtr)
				/* OUTPUT: Position of the terminal '\0'
				 *         at the end of the returned string */
{

    char* retval = ckalloc(len + 1);
				/* Output buffer */
    mp_int b;			/* Numerator of the fraction being converted */

    mp_int mplus, mminus;	/* Bounds for roundoff */
    mp_digit digit;		/* Current output digit */
    char* s = retval;		/* Cursor in the output buffer */
    int i;			/* Index in the output buffer */
    mp_int temp;
    int r1;

    /*
     * b = bw * 2**b2 * 5**b5
     * mminus = 5**m5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    mp_init_set_int(&mminus, 1);
    MulPow5(&b, b5, &b);
    mp_mul_2d(&b, b2, &b);


    /* Adjust if the logarithm was guessed wrong */


    if (b.used <= sd) {
	mp_mul_d(&b, 10, &b);
	++m2plus; ++m2minus; ++m5;
	ilim = ilim1;
	--k;
    }
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481

3482

3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511

3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587

3588
3589
3590


3591
3592

3593

3594
3595

3596

3597

3598

3599

3600
3601
3602

3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661

3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739

3740

3741

3742
3743
3744

3745

3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793


3794

3795
3796


3797

3798

3799

3800

3801

3802

3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871

3872

3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969

3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985

3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009


4010
4011

4012
4013
4014

4015

4016

4017

4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043

4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073

4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102


4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129

4130

4131

4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149

4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240

4241

4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281

4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294

4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306

4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328

4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354

4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384

4385
4386
4387
4388
4389
4390
4391
4392
4393

4394

4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413

4414
4415

4416
4417
4418
4419
4420
4421


4422
4423


4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441

4442
4443
4444
4445
4446
4447
4448
4449

4450

4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466

4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480

4481
4482
4483
4484
4485
4486
4487
    MulPow5(&mminus, m5, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);

    /*
     * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
     * by mp_digit extraction.
     */

    i = 0;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {
	    digit = b.dp[sd];
	    if (b.used > sd+1 || digit >= 10) {
		Tcl_Panic("wrong digit!");
	    }
	    --b.used; mp_clamp(&b);
	}

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 */

	r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
	if (r1 == MP_LT || (r1 == MP_EQ

		&& convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) {

	    /*
	     * Make sure we shouldn't be rounding *up* instead, in case the
	     * next number above is closer.
	     */

	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }

	    /*
	     * Stash the last digit.
	     */

	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does one plus the current digit put us within roundoff of the
	 * number?
	 */

	if (ShouldBankerRoundUpToNextPowD(&b, &mminus, sd, convType,
		dPtr->w.word1 & 1, &temp)) {

	    if (digit == 9) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    ++digit;
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}

	/*
	 * Advance to the next digit.
	 */

	mp_mul_d(&b, 10, &b);
	mp_mul_d(&mminus, 10, &mminus);
	if (m2plus > m2minus) {
	    mp_mul_2d(&mminus, m2plus-m2minus, &mplus);
	}
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &temp, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * StrictBignumConversionPowD --
 *
 *	Converts a double-precision number to a fixed-lengt string of 'ilim'
 *	digits (or 'ilim1' if log10(d) has been overestimated).  The
 *	denominator in David Gay's conversion algorithm is known to be a power
 *	of 2**MP_DIGIT_BIT, and hence the division in the main loop may be
 *	replaced by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly allocated
 *	memory.
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the location
 *	of the terminal null byte in '*endPtr'.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictBignumConversionPowD(
    Double *dPtr,		/* Original number to convert. */

    int convType,		/* Type of conversion (shortest, Steele,
				 * E format, F format). */
    Tcl_WideUInt bw,		/* Integer significand. */


    int b2, int b5,		/* Scale factor for the significand in the
				 * numerator. */

    int sd,			/* Scale factor for the denominator. */

    int k,			/* Number of output digits before the decimal
				 * point. */

    int len,			/* Number of digits to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Position of the terminal '\0' at
				 *	   the end of the returned string. */
{

    char *retval = ckalloc(len + 1);
				/* Output buffer. */
    mp_int b;			/* Numerator of the fraction being
				 * converted. */
    mp_digit digit;		/* Current output digit. */
    char *s = retval;		/* Cursor in the output buffer. */
    int i;			/* Index in the output buffer. */
    mp_int temp;

    /*
     * b = bw * 2**b2 * 5**b5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    MulPow5(&b, b5, &b);
    mp_mul_2d(&b, b2, &b);

    /*
     * Adjust if the logarithm was guessed wrong.
     */

    if (b.used <= sd) {
	mp_mul_d(&b, 10, &b);
	ilim = ilim1;
	--k;
    }
    mp_init(&temp);

    /*
     * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT)
     * by mp_digit extraction.
     */

    i = 1;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {
	    digit = b.dp[sd];
	    if (b.used > sd+1 || digit >= 10) {
		Tcl_Panic("wrong digit!");
	    }
	    --b.used;
	    mp_clamp(&b);
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		s = BumpUp(s, retval, &k);
	    }
	    while (*--s == '0') {
		/* do nothing */
	    }
	    ++s;

	    break;
	}

	/*
	 * Advance to the next digit.
	 */

	mp_mul_d(&b, 10, &b);
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &temp, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUp --
 *
 *	Tests whether a digit should be rounded up or down when finishing
 *	bignum-based floating point conversion.
 *
 * Results:
 *	Returns 1 if the number needs to be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUp(
    mp_int *twor,		/* 2x the remainder from thd division that
				 * produced the last digit. */
    mp_int *S,			/* Denominator. */
    int isodd)			/* Flag == 1 if the last digit is odd. */
{
    int r = mp_cmp_mag(twor, S);

    switch (r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!");
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNext --
 *
 *	Tests whether the remainder is great enough to force rounding to the
 *	next higher digit.
 *
 * Results:
 *	Returns 1 if the number should be rounded up, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static inline int
ShouldBankerRoundUpToNext(
    mp_int *b,			/* Remainder from the division that produced
				 * the last digit. */

    mp_int *m,			/* Numerator of the rounding tolerance. */

    mp_int *S,			/* Denominator. */

    int convType,		/* Conversion type: STEELE0 defeats
				 * round-to-even. (Not sure why one would want
				 * this; I coped it from Gay). FIXME */

    int isodd,			/* 1 if the integer significand is odd. */

    mp_int *temp)		/* Work area needed for the calculation. */
{
    int r;

    /*
     * Compare b and S-m: this is the same as comparing B+m and S.
     */

    mp_add(b, m, temp);
    r = mp_cmp_mag(temp, S);
    switch(r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	if (convType == TCL_DD_STEELE0) {
	    return 0;
	} else {
	    return isodd;
	}
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!");
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningBignumConversion --
 *
 *	Convert a floating point number to a variable-length digit string
 *	using the multiprecision method.
 *
 * Results:
 *	Returns the string of digits.
 *
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

static inline char *
ShorteningBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */


    Tcl_WideUInt bw,		/* Integer significand and exponent. */

    int b2,			/* Scale factor for the significand. */
    int m2plus, int m2minus,	/* Scale factors for 1/2 ulp in numerator. */


    int s2, int s5,		/* Scale factors for denominator. */

    int k,			/* Guessed position of the decimal point. */

    int len,			/* Size of the digit buffer to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Pointer to the end of the number */
{
    char *retval = ckalloc(len+1);
				/* Buffer of digits to return. */
    char *s = retval;		/* Cursor in the return value. */
    mp_int b;			/* Numerator of the result. */
    mp_int mminus;		/* 1/2 ulp below the result. */
    mp_int mplus;		/* 1/2 ulp above the result. */
    mp_int S;			/* Denominator of the result. */
    mp_int dig;			/* Current digit of the result. */
    int digit;			/* Current digit of the result. */
    mp_int temp;		/* Work area. */
    int minit = 1;		/* Fudge factor for when we misguess k. */
    int i;
    int r1;

    /*
     * b = bw * 2**b2 * 5**b5
     * S = 2**s2 * 5*s5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    mp_mul_2d(&b, b2, &b);
    mp_init_set(&S, 1);
    MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);

    /*
     * Handle the case where we guess the position of the decimal point wrong.

     */

    if (mp_cmp_mag(&b, &S) == MP_LT) {
	mp_mul_d(&b, 10, &b);
	minit = 10;
	ilim =ilim1;
	--k;
    }

    /*
     * mminus = 2**m2minus * 5**m5
     */

    mp_init_set(&mminus, minit);
    mp_mul_2d(&mminus, m2minus, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);

    /*
     * Loop through the digits.
     */

    mp_init(&dig);
    i = 1;
    for (;;) {
	mp_div(&b, &S, &dig, &b);
	if (dig.used > 1 || dig.dp[0] >= 10) {
	    Tcl_Panic("wrong digit!");
	}
	digit = dig.dp[0];

	/*
	 * Does the current digit leave us with a remainder small enough to
	 * round to it?
	 */

	r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
	if (r1 == MP_LT || (r1 == MP_EQ

		&& convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) {

	    mp_mul_2d(&b, 1, &b);
	    if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does the current digit leave us with a remainder large enough to
	 * commit to rounding up to the next higher digit?
	 */

	if (ShouldBankerRoundUpToNext(&b, &mminus, &S, convType,
		dPtr->w.word1 & 1, &temp)) {
	    ++digit;
	    if (digit == 10) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    mp_mul_2d(&b, 1, &b);
	    if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}

	/*
	 * Advance to the next digit.
	 */

	if (s5 > 0) {
	    /*
	     * Can possibly shorten the denominator.
	     */

	    mp_mul_2d(&b, 1, &b);
	    mp_mul_2d(&mminus, 1, &mminus);
	    if (m2plus > m2minus) {
		mp_mul_2d(&mplus, 1, &mplus);
	    }
	    mp_div_d(&S, 5, &S, NULL);
	    --s5;

	    /*
	     * IDEA: It might possibly be a win to fall back to int64_t
	     *       arithmetic here if S < 2**64/10. But it's a win only for
	     *       a fairly narrow range of magnitudes so perhaps not worth
	     *       bothering.  We already know that we shorten the
	     *       denominator by at least 1 mp_digit, perhaps 2, as we do
	     *       the conversion for 17 digits of significance.
	     * Possible savings:
	     * 10**26   1 trip through loop before fallback possible
	     * 10**27   1 trip
	     * 10**28   2 trips
	     * 10**29   3 trips
	     * 10**30   4 trips
	     * 10**31   5 trips
	     * 10**32   6 trips
	     * 10**33   7 trips
	     * 10**34   8 trips
	     * 10**35   9 trips
	     * 10**36  10 trips
	     * 10**37  11 trips
	     * 10**38  12 trips
	     * 10**39  13 trips
	     * 10**40  14 trips
	     * 10**41  15 trips
	     * 10**42  16 trips
	     * thereafter no gain.
	     */
	} else {
	    mp_mul_d(&b, 10, &b);
	    mp_mul_d(&mminus, 10, &mminus);
	    if (m2plus > m2minus) {
		mp_mul_2d(&mplus, 10, &mplus);
	    }
	}

	++i;
    }


    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &temp, &dig, &S, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;

}

/*
 *----------------------------------------------------------------------
 *
 * StrictBignumConversion --
 *
 *	Convert a floating point number to a fixed-length digit string using
 *	the multiprecision method.
 *
 * Results:
 *	Returns the string of digits.
 *
 * Side effects:
 *	Stores the position of the decimal point in *decpt.  Stores a pointer
 *	to the end of the number in *endPtr.
 *
 *----------------------------------------------------------------------
 */

static inline char *
StrictBignumConversion(
    Double *dPtr,		/* Original number being converted. */
    int convType,		/* Conversion type. */


    Tcl_WideUInt bw,		/* Integer significand and exponent. */
    int b2,			/* Scale factor for the significand. */

    int s2, int s5,		/* Scale factors for denominator. */
    int k,			/* Guessed position of the decimal point. */
    int len,			/* Size of the digit buffer to allocate. */

    int ilim,			/* Number of digits to convert if b >= s */

    int ilim1,			/* Number of digits to convert if b < s */

    int *decpt,			/* OUTPUT: Position of the decimal point. */

    char **endPtr)		/* OUTPUT: Pointer to the end of the number */
{
    char *retval = ckalloc(len+1);
				/* Buffer of digits to return. */
    char *s = retval;		/* Cursor in the return value. */
    mp_int b;			/* Numerator of the result. */
    mp_int S;			/* Denominator of the result. */
    mp_int dig;			/* Current digit of the result. */
    int digit;			/* Current digit of the result. */
    mp_int temp;		/* Work area. */
    int g;			/* Size of the current digit ground. */
    int i, j;

    /*
     * b = bw * 2**b2 * 5**b5
     * S = 2**s2 * 5*s5
     */

    mp_init_multi(&temp, &dig, NULL);
    TclBNInitBignumFromWideUInt(&b, bw);
    mp_mul_2d(&b, b2, &b);
    mp_init_set(&S, 1);
    MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);

    /*
     * Handle the case where we guess the position of the decimal point wrong.

     */

    if (mp_cmp_mag(&b, &S) == MP_LT) {
	mp_mul_d(&b, 10, &b);
	ilim =ilim1;
	--k;
    }

    /*
     * Convert the leading digit.
     */

    i = 0;
    mp_div(&b, &S, &dig, &b);
    if (dig.used > 1 || dig.dp[0] >= 10) {
	Tcl_Panic("wrong digit!");
    }
    digit = dig.dp[0];

    /*
     * Is a single digit all that was requested?
     */

    *s++ = '0' + digit;
    if (++i >= ilim) {
	mp_mul_2d(&b, 1, &b);
	if (ShouldBankerRoundUp(&b, &S, digit&1)) {
	    s = BumpUp(s, retval, &k);
	}
    } else {

	for (;;) {
	    /*
	     * Shift by a group of digits.
	     */

	    g = ilim - i;
	    if (g > DIGIT_GROUP) {
		g = DIGIT_GROUP;
	    }
	    if (s5 >= g) {
		mp_div_d(&S, dpow5[g], &S, NULL);
		s5 -= g;
	    } else if (s5 > 0) {
		mp_div_d(&S, dpow5[s5], &S, NULL);
		mp_mul_d(&b, dpow5[g - s5], &b);
		s5 = 0;
	    } else {
		mp_mul_d(&b, dpow5[g], &b);
	    }
	    mp_mul_2d(&b, g, &b);

	    /*
	     * As with the shortening bignum conversion, it's possible at this
	     * point that we will have reduced the denominator to less than
	     * 2**64/10, at which point it would be possible to fall back to
	     * to int64_t arithmetic. But the potential payoff is tremendously
	     * less - unless we're working in F format - because we know that
	     * three groups of digits will always suffice for %#.17e, the
	     * longest format that doesn't introduce empty precision.


	     *
	     * Extract the next group of digits.
	     */

	    mp_div(&b, &S, &dig, &b);
	    if (dig.used > 1) {
		Tcl_Panic("wrong digit!");
	    }
	    digit = dig.dp[0];
	    for (j = g-1; j >= 0; --j) {
		int t = itens[j];

		*s++ = digit / t + '0';
		digit %= t;
	    }
	    i += g;

	    /*
	     * Have we converted all the requested digits?
	     */

	    if (i == ilim) {
		mp_mul_2d(&b, 1, &b);
		if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		    s = BumpUp(s, retval, &k);
		}
		break;

	    }

	}

    }
    while (*--s == '0') {
	/* do nothing */
    }
    ++s;

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &S, &temp, &dig, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;

}

/*
 *----------------------------------------------------------------------
 *
 * TclDoubleDigits --
 *
 *	Core of Tcl's conversion of double-precision floating point numbers to
 *	decimal.
 *
 * Results:
 *	Returns a newly-allocated string of digits.
 *
 * Side effects:
 *	Sets *decpt to the index of the character in the string before the
 *	place that the decimal point should go. If 'endPtr' is not NULL, sets
 *	endPtr to point to the terminating '\0' byte of the string. Sets *sign
 *	to 1 if a minus sign should be printed with the number, or 0 if a plus
 *	sign (or no sign) should appear.
 *
 * This function is a service routine that produces the string of digits for
 * floating-point-to-decimal conversion. It can do a number of things
 * according to the 'flags' argument. Valid values for 'flags' include:
 *	TCL_DD_SHORTEST - This is the default for floating point conversion if
 *		::tcl_precision is 0. It constructs the shortest string of
 *		digits that will reconvert to the given number when scanned.
 *		For floating point numbers that are exactly between two
 *		decimal numbers, it resolves using the 'round to even' rule.
 *		With this value, the 'ndigits' parameter is ignored.
 *	TCL_DD_STEELE - This value is not recommended and may be removed in
 *		the future. It follows the conversion algorithm outlined in
 *		"How to Print Floating-Point Numbers Accurately" by Guy
 *		L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90,
 *		pp. 112-126]. This rule has the effect of rendering 1e23 as
 *		9.9999999999999999e22 - which is a 'better' approximation in
 *		the sense that it will reconvert correctly even if a
 *		subsequent input conversion is 'round up' or 'round down'
 *		rather than 'round to nearest', but is surprising otherwise.
 *	TCL_DD_E_FORMAT - This value is used to prepare numbers for %e format
 *		conversion (or for default floating->string if tcl_precision
 *		is not 0). It constructs a string of at most 'ndigits' digits,
 *		choosing the one that is closest to the given number (and
 *		resolving ties with 'round to even').  It is allowed to return
 *		fewer than 'ndigits' if the number converts exactly; if the
 *		TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG is supplied instead, it
 *		also returns fewer digits if the shorter string will still
 *		reconvert without loss to the given input number. In any case,
 *		strings of trailing zeroes are suppressed.
 *	TCL_DD_F_FORMAT - This value is used to prepare numbers for %f format
 *		conversion. It requests that conversion proceed until
 *		'ndigits' digits after the decimal point have been converted.
 *		It is possible for this format to result in a zero-length
 *		string if the number is sufficiently small. Again, it is
 *		permissible for TCL_DD_F_FORMAT to return fewer digits for a
 *		number that converts exactly, and changing the argument to
 *		TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow the routine
 *		also to return fewer digits if the shorter string will still
 *		reconvert without loss to the given input number. Strings of
 *		trailing zeroes are suppressed.
 *
 *	To any of these flags may be OR'ed TCL_DD_NO_QUICK; this flag requires
 *	all calculations to be done in exact arithmetic. Normally, E and F
 *	format with fewer than about 14 digits will be done with a quick
 *	floating point approximation and fall back on the exact arithmetic
 *	only if the input number is close enough to the midpoint between two
 *	decimal strings that more precision is needed to resolve which string
 *	is correct.
 *
 * The value stored in the 'decpt' argument on return may be negative
 * (indicating that the decimal point falls to the left of the string) or
 * greater than the length of the string. In addition, the value -9999 is used
 * as a sentinel to indicate that the string is one of the special values
 * "Infinity" and "NaN", and that no decimal point should be inserted.
 *
 *----------------------------------------------------------------------
 */

char *
TclDoubleDigits(
    double dv,			/* Number to convert. */
    int ndigits,		/* Number of digits requested. */
    int flags,			/* Conversion flags. */
    int *decpt,			/* OUTPUT: Position of the decimal point. */
    int *sign,			/* OUTPUT: 1 if the result is negative. */
    char **endPtr)		/* OUTPUT: If not NULL, receives a pointer to
				 *	   one character beyond the end of the
				 *	   returned string. */
{
    int convType = (flags & TCL_DD_CONVERSION_TYPE_MASK);
				/* Type of conversion being performed:
				 * TCL_DD_SHORTEST0, TCL_DD_STEELE0,

				 * TCL_DD_E_FORMAT, or TCL_DD_F_FORMAT. */

    Double d;			/* Union for deconstructing doubles. */
    Tcl_WideUInt bw;		/* Integer significand. */
    int be;			/* Power of 2 by which b must be multiplied */
    int bbits;			/* Number of bits needed to represent b. */
    int denorm;			/* Flag == 1 iff the input number was
				 * denormalized. */
    int k;			/* Estimate of floor(log10(d)). */
    int k_check;		/* Flag == 1 if d is near enough to a power of
				 * ten that k must be checked. */
    int b2, b5, s2, s5;		/* Powers of 2 and 5 in the numerator and
				 * denominator of intermediate results. */
    int ilim = -1, ilim1 = -1;	/* Number of digits to convert, and number to
				 * convert if log10(d) has been
				 * overestimated. */
    char *retval;		/* Return value from this function. */
    int i = -1;

    /*
     * Put the input number into a union for bit-whacking.
     */

    d.d = dv;

    /*
     * Handle the cases of negative numbers (by taking the absolute value:
     * this includes -Inf and -NaN!), infinity, Not a Number, and zero.
     */

    TakeAbsoluteValue(&d, sign);
    if ((d.w.word0 & EXP_MASK) == EXP_MASK) {
	return FormatInfAndNaN(&d, decpt, endPtr);
    }
    if (d.d == 0.0) {
	return FormatZero(decpt, endPtr);
    }

    /*
     * Unpack the floating point into a wide integer and an exponent.
     * Determine the number of bits that the big integer requires, and compute
     * a quick approximation (which may be one too high) of ceil(log10(d.d)).

     */

    denorm = ((d.w.word0 & EXP_MASK) == 0);
    DoubleToExpAndSig(d.d, &bw, &be, &bbits);
    k = ApproximateLog10(bw, be, bbits);
    k = BetterLog10(d.d, k, &k_check);

    /* At this point, we have:
     *	  d is the number to convert.
     *    bw are significand and exponent: d == bw*2**be,
     *    bbits is the length of bw: 2**bbits-1 <= bw < 2**bbits
     *	  k is either ceil(log10(d)) or ceil(log10(d))+1. k_check is 0 if we
     *      know that k is exactly ceil(log10(d)) and 1 if we need to check.

     *    We want a rational number
     *      r = b * 10**(1-k) = bw * 2**b2 * 5**b5 / (2**s2 / 5**s5),
     *    with b2, b5, s2, s5 >= 0.  Note that the most significant decimal
     *    digit is floor(r) and that successive digits can be obtained by
     *    setting r <- 10*floor(r) (or b <= 10 * (b % S)).  Find appropriate
     *    b2, b5, s2, s5.
     */

    ComputeScale(be, k, &b2, &b5, &s2, &s5);

    /*
     * Correct an incorrect caller-supplied 'ndigits'.  Also determine:

     *	i = The maximum number of decimal digits that will be returned in the
     *      formatted string.  This is k + 1 + ndigits for F format, 18 for
     *      shortest and Steele, and ndigits for E format.
     *  ilim = The number of significant digits to convert if k has been
     *         guessed correctly. This is -1 for shortest and Steele (which
     *         stop when all significance has been lost), 'ndigits' for E
     *         format, and 'k + 1 + ndigits' for F format.
     *  ilim1 = The minimum number of significant digits to convert if k has
     *	        been guessed 1 too high. This, too, is -1 for shortest and
     *	        Steele, and 'ndigits' for E format, but it's 'ndigits-1' for F
     *	        format.
     */

    SetPrecisionLimits(convType, k, &ndigits, &i, &ilim, &ilim1);

    /*
     * Try to do low-precision conversion in floating point rather than
     * resorting to expensive multiprecision arithmetic.
     */

    if (ilim >= 0 && ilim <= QUICK_MAX && !(flags & TCL_DD_NO_QUICK)) {
	retval = QuickConversion(d.d, k, k_check, flags, i, ilim, ilim1,

		decpt, endPtr);
	if (retval != NULL) {
	    return retval;
	}
    }

    /*
     * For shortening conversions, determine the upper and lower bounds for
     * the remainder at which we can stop.
     *   m+ = (2**m2plus * 5**m5) / (2**s2 * 5**s5) is the limit on the high
     *        side, and
     *   m- = (2**m2minus * 5**m5) / (2**s2 * 5**s5) is the limit on the low
     *        side.
     * We may need to increase s2 to put m2plus, m2minus, b2 over a common
     * denominator.
     */

    if (flags & TCL_DD_SHORTEN_FLAG) {
	int m2minus = b2;
	int m2plus;
	int m5 = b5;
	int len = i;

	/*
	 * Find the quantity i so that (2**i*5**b5)/(2**s2*5**s5) is 1/2 unit
	 * in the least significant place of the floating point number.

	 */

	if (denorm) {
	    i = be + EXPONENT_BIAS + (FP_PRECISION-1);
	} else {
	    i = 1 + FP_PRECISION - bbits;
	}
	b2 += i;
	s2 += i;

	/*
	 * Reduce the fractions to lowest terms, since the above calculation
	 * may have left excess powers of 2 in numerator and denominator.
	 */

	CastOutPowersOf2(&b2, &m2minus, &s2);

	/*
	 * In the special case where bw==1, the nearest floating point number
	 * to it on the low side is 1/4 ulp below it. Adjust accordingly.
	 */

	m2plus = m2minus;
	if (!denorm && bw == 1) {
	    ++b2;
	    ++s2;
	    ++m2plus;
	}

	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) {

	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word,
	     * then all our intermediate calculations can be done using exact
	     * 64-bit arithmetic with no need for expensive multiprecision
	     * operations. (This will be true for all numbers in the range
	     * [1.0e-3 .. 1.0e+24]).
	     */

	    return ShorteningInt64Conversion(&d, convType, bw, b2, b5, m2plus,

		    m2minus, m5, s2, s5, k, len, ilim, ilim1, decpt, endPtr);

	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division by
	     * digit shifts. First we round up s2 to a multiple of MP_DIGIT_BIT,
	     * and adjust m2 and b2 accordingly. Then we launch into a version
	     * of the comparison that's specialized for the 'power of mp_digit
	     * in the denominator' case.
	     */

	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);

		b2 += delta;
		m2plus += delta;
		m2minus += delta;
		s2 += delta;
	    }
	    return ShorteningBignumConversionPowD(&d, convType, bw, b2, b5,
		    m2plus, m2minus, m5, s2/MP_DIGIT_BIT, k, len, ilim, ilim1,

		    decpt, endPtr);
	} else {

	    /*
	     * Alas, there's no helpful special case; use full-up bignum
	     * arithmetic for the conversion.
	     */

	    return ShorteningBignumConversion(&d, convType, bw, b2, m2plus,


		    m2minus, s2, s5, k, len, ilim, ilim1, decpt, endPtr);
	}


    } else {
	/*
	 * Non-shortening conversion.
	 */

	int len = i;

	/*
	 * Reduce numerator and denominator to lowest terms.
	 */

	if (b2 >= s2 && s2 > 0) {
	    b2 -= s2; s2 = 0;
	} else if (s2 >= b2 && b2 > 0) {
	    s2 -= b2; b2 = 0;
	}

	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) {

	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word,
	     * then all our intermediate calculations can be done using exact
	     * 64-bit arithmetic with no need for expensive multiprecision
	     * operations.
	     */

	    return StrictInt64Conversion(&d, convType, bw, b2, b5, s2, s5, k,

		    len, ilim, ilim1, decpt, endPtr);

	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division by
	     * digit shifts. First we round up s2 to a multiple of MP_DIGIT_BIT,
	     * and adjust m2 and b2 accordingly. Then we launch into a version
	     * of the comparison that's specialized for the 'power of mp_digit
	     * in the denominator' case.
	     */

	    if (s2 % MP_DIGIT_BIT != 0) {
		int delta = MP_DIGIT_BIT - (s2 % MP_DIGIT_BIT);

		b2 += delta;
		s2 += delta;
	    }
	    return StrictBignumConversionPowD(&d, convType, bw, b2, b5,

		    s2/MP_DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr);
	} else {
	    /*
	     * There are no helpful special cases, but at least we know in
	     * advance how many digits we will convert. We can run the
	     * conversion in steps of DIGIT_GROUP digits, so as to have many
	     * fewer mp_int divisions.
	     */

	    return StrictBignumConversion(&d, convType, bw, b2, s2, s5, k,
		    len, ilim, ilim1, decpt, endPtr);
	}
    }
}


/*
 *----------------------------------------------------------------------
 *
 * TclInitDoubleConversion --
 *
 *	Initializes constants that are needed for conversions to and from







<
|
|
<



















|
>
|
>

|
|

<









<
|
<










|
|
>













<








<
|
<













<













|



|
|
|
|
|


|
|


|
|

|


|
|
|
>
|
|
|
>
>
|
|
>
|
>
|
|
>
|
>
|
>
|
>
|
>
|
|

>
|
|
|
<
|
|
|










<
|
<









|
|











|
<





<




|
|
|
|
|
>



<
|
<









<










|









|


|
|
|
|
|
|


<













|



|
|




|


|
|
|

>
|
>
|
>
|
|
|
>
|
>
|


<
<
|
<
<



















|










|
|

|


|
|
|
|
>
>
|
>
|
|
>
>
|
>
|
>
|
>
|
>
|
>
|
>
|

|
|
|
|
|
|
|
|
|
|
|










|



|
>









<
|
<

|







<
|
<
















|
>
|
>














|
|



|










<
|
<










<
|
<


|
|
<
<







<

|
|
|
|
|
|


















|











>





<










>



|



|
|





|
|

|


|
|
|
|
>
>
|
|
>
|
|
|
>
|
>
|
>
|
>
|

|
|
|
|
|
|
|
|
|










|



|
>








<
|
<








<
|
<








>

|
|
<


















|
|
|
|
|
|
|
>
>
|
|
<








<





<
|
<





|
|
>
|
>
|
>
|
<
<
|
<
|




<







>



|



|
|






|
|
|
|

|
|

|
|
|



|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|

|
|
|
|
|
|
|


|
|
|
|

|

<
|
|
<
|
|
|
|
|
|
|


|
|
>
|
>
|
|

|

|
|
|
|

|
|
|
|
|


<
|
<


















|
|
>

<









|
|
>



|
|
|





|
>


|
|
|
|
|
|
|
|
|





|
|

<

|
>
|
<





|
|
|
|
|
|
|
|









|
|
>

<










|

<






<







|
>

|
|
|
|
|


|
>
|
>


|
|
|
|
|

<
|
|
<






|
>
|

>

|
|


|
>
>
|
|
>
>

|
|
<



<
|
<







|
>

|
|
|
|


|
>
|
>


|
|
|
|
|

<
|
|
<




>
|


|
|
|
|

<
|
|



>







3285
3286
3287
3288
3289
3290
3291

3292
3293

3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320

3321
3322
3323
3324
3325
3326
3327
3328
3329

3330

3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356

3357
3358
3359
3360
3361
3362
3363
3364

3365

3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378

3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444

3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457

3458

3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486

3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499

3500

3501
3502
3503
3504
3505
3506
3507
3508
3509

3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584


3585


3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683

3684

3685
3686
3687
3688
3689
3690
3691
3692
3693

3694

3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744

3745

3746
3747
3748
3749
3750
3751
3752
3753
3754
3755

3756

3757
3758
3759
3760


3761
3762
3763
3764
3765
3766
3767

3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895

3896

3897
3898
3899
3900
3901
3902
3903
3904

3905

3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917

3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946

3947
3948
3949
3950
3951
3952
3953
3954

3955
3956
3957
3958
3959

3960

3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973


3974

3975
3976
3977
3978
3979

3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063

4064
4065

4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096

4097

4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119

4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163

4164
4165
4166
4167

4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193

4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205

4206
4207
4208
4209
4210
4211

4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240

4241
4242

4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268

4269
4270
4271

4272

4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300

4301
4302

4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
    MulPow5(&mminus, m5, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);


    /* Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
     * by mp_digit extraction */


    i = 0;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {
	    digit = b.dp[sd];
	    if (b.used > sd+1 || digit >= 10) {
		Tcl_Panic("wrong digit!");
	    }
	    --b.used; mp_clamp(&b);
	}

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 */

	r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
	if (r1 == MP_LT
	    || (r1 == MP_EQ
		&& convType != TCL_DD_STEELE0
		&& (dPtr->w.word1 & 1) == 0)) {
	    /*
	     * Make sure we shouldn't be rounding *up* instead,
	     * in case the next number above is closer
	     */

	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }


	    /* Stash the last digit */


	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does one plus the current digit put us within roundoff of the
	 * number?
	 */

	if (ShouldBankerRoundUpToNextPowD(&b, &mminus, sd,
					   convType, dPtr->w.word1 & 1,
					   &temp)) {
	    if (digit == 9) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    ++digit;
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}


	/* Advance to the next digit */


	mp_mul_d(&b, 10, &b);
	mp_mul_d(&mminus, 10, &mminus);
	if (m2plus > m2minus) {
	    mp_mul_2d(&mminus, m2plus-m2minus, &mplus);
	}
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &temp, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * StrictBignumConversionPowD --
 *
 *	Converts a double-precision number to a fixed-lengt string of
 *	'ilim' digits (or 'ilim1' if log10(d) has been overestimated.)
 *	The denominator in David Gay's conversion algorithm is known to
 *	be a power of 2**DIGIT_BIT, and hence the division in the main
 *	loop may be replaced by a digit shift and mask.
 *
 * Results:
 *	Returns the string of significant decimal digits, in newly
 *	allocated memory.
 *
 * Side effects:
 *	Stores the location of the decimal point in '*decpt' and the
 *      location of the terminal null byte in '*endPtr'.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
StrictBignumConversionPowD(Double* dPtr,
				/* Original number to convert */
			   int convType,
				/* Type of conversion (shortest, Steele,
				   E format, F format) */
			   Tcl_WideUInt bw,
				/* Integer significand */
			   int b2, int b5,
				/* Scale factor for the significand
				 * in the numerator */
			   int sd,
				/* Scale factor for the denominator */
			   int k,
				/* Number of output digits before the decimal
				 * point */
			   int len,
				/* Number of digits to allocate */
			   int ilim,
				/* Number of digits to convert if b >= s */
			   int ilim1,
				/* Number of digits to convert if b < s */
			   int* decpt,
				/* OUTPUT: Position of the decimal point */
			   char** endPtr)
				/* OUTPUT: Position of the terminal '\0'
				 *         at the end of the returned string */
{

    char* retval = ckalloc(len + 1);
				/* Output buffer */
    mp_int b;			/* Numerator of the fraction being converted */

    mp_digit digit;		/* Current output digit */
    char* s = retval;		/* Cursor in the output buffer */
    int i;			/* Index in the output buffer */
    mp_int temp;

    /*
     * b = bw * 2**b2 * 5**b5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    MulPow5(&b, b5, &b);
    mp_mul_2d(&b, b2, &b);


    /* Adjust if the logarithm was guessed wrong */


    if (b.used <= sd) {
	mp_mul_d(&b, 10, &b);
	ilim = ilim1;
	--k;
    }
    mp_init(&temp);

    /*
     * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
     * by mp_digit extraction
     */

    i = 1;
    for (;;) {
	if (b.used <= sd) {
	    digit = 0;
	} else {
	    digit = b.dp[sd];
	    if (b.used > sd+1 || digit >= 10) {
		Tcl_Panic("wrong digit!");
	    }
	    --b.used; mp_clamp(&b);

	}

	/*
	 * Have we converted all the requested digits?
	 */

	*s++ = '0' + digit;
	if (i == ilim) {
	    if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
		s = BumpUp(s, retval, &k);
	    } else {
		while (*--s == '0') {
		    /* do nothing */
		}
		++s;
	    }
	    break;
	}


	/* Advance to the next digit */


	mp_mul_d(&b, 10, &b);
	++i;
    }

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &temp, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUp --
 *
 *	Tests whether a digit should be rounded up or down when finishing
 *	bignum-based floating point conversion.
 *
 * Results:
 *	Returns 1 if the number needs to be rounded up, 0 otherwise.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUp(mp_int* twor,
				/* 2x the remainder from thd division that
				 * produced the last digit */
		    mp_int* S,	/* Denominator */
		    int isodd)	/* Flag == 1 if the last digit is odd */
{
    int r = mp_cmp_mag(twor, S);

    switch (r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!");
    return 0;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNext --
 *
 *	Tests whether the remainder is great enough to force rounding
 *	to the next higher digit.
 *
 * Results:
 *	Returns 1 if the number should be rounded up, 0 otherwise.
 *
 *-----------------------------------------------------------------------------
 */

inline static int
ShouldBankerRoundUpToNext(mp_int* b,
				/* Remainder from the division that produced
				 * the last digit. */
			  mp_int* m,
				/* Numerator of the rounding tolerance */
			  mp_int* S,
				/* Denominator */
			  int convType,
				/* Conversion type: STEELE0 defeats
				 * round-to-even. (Not sure why one would
				 * want this; I coped it from Gay. FIXME */
			  int isodd,
				/* 1 if the integer significand is odd */
			  mp_int* temp)
				/* Work area needed for the calculation */
{
    int r;


    /* Compare b and S-m: this is the same as comparing B+m and S. */


    mp_add(b, m, temp);
    r = mp_cmp_mag(temp, S);
    switch(r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	if (convType == TCL_DD_STEELE0) {
	    return 0;
	} else {
	    return isodd;
	}
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!");
    return 0;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ShorteningBignumConversion --
 *
 *	Convert a floating point number to a variable-length digit string
 *	using the multiprecision method.
 *
 * Results:
 *	Returns the string of digits.
 *
 * Side effects:
 *	Stores the position of the decimal point in *decpt.
 *	Stores a pointer to the end of the number in *endPtr.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
ShorteningBignumConversion(Double* dPtr,
				/* Original number being converted */
			   int convType,
				/* Conversion type */
			   Tcl_WideUInt bw,
				/* Integer significand and exponent */
			   int b2,
				/* Scale factor for the significand */
			   int m2plus, int m2minus,
				/* Scale factors for 1/2 ulp in numerator */
			   int s2, int s5,
				/* Scale factors for denominator */
			   int k,
				/* Guessed position of the decimal point */
			   int len,
				/* Size of the digit buffer to allocate */
			   int ilim,
				/* Number of digits to convert if b >= s */
			   int ilim1,
				/* Number of digits to convert if b < s */
			   int* decpt,
				/* OUTPUT: Position of the decimal point */
			   char** endPtr)
				/* OUTPUT: Pointer to the end of the number */
{
    char* retval = ckalloc(len+1);
				/* Buffer of digits to return */
    char* s = retval;		/* Cursor in the return value */
    mp_int b;			/* Numerator of the result */
    mp_int mminus;		/* 1/2 ulp below the result */
    mp_int mplus;		/* 1/2 ulp above the result */
    mp_int S;			/* Denominator of the result */
    mp_int dig;			/* Current digit of the result */
    int digit;			/* Current digit of the result */
    mp_int temp;		/* Work area */
    int minit = 1;		/* Fudge factor for when we misguess k */
    int i;
    int r1;

    /*
     * b = bw * 2**b2 * 5**b5
     * S = 2**s2 * 5*s5
     */

    TclBNInitBignumFromWideUInt(&b, bw);
    mp_mul_2d(&b, b2, &b);
    mp_init_set_int(&S, 1);
    MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);

    /*
     * Handle the case where we guess the position of the decimal point
     * wrong.
     */

    if (mp_cmp_mag(&b, &S) == MP_LT) {
	mp_mul_d(&b, 10, &b);
	minit = 10;
	ilim =ilim1;
	--k;
    }


    /* mminus = 2**m2minus * 5**m5 */


    mp_init_set_int(&mminus, minit);
    mp_mul_2d(&mminus, m2minus, &mminus);
    if (m2plus > m2minus) {
	mp_init_copy(&mplus, &mminus);
	mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
    }
    mp_init(&temp);


    /* Loop through the digits */


    mp_init(&dig);
    i = 1;
    for (;;) {
	mp_div(&b, &S, &dig, &b);
	if (dig.used > 1 || dig.dp[0] >= 10) {
	    Tcl_Panic("wrong digit!");
	}
	digit = dig.dp[0];

	/*
	 * Does the current digit leave us with a remainder small enough to
	 * round to it?
	 */

	r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
	if (r1 == MP_LT
	    || (r1 == MP_EQ
		&& convType != TCL_DD_STEELE0
		&& (dPtr->w.word1 & 1) == 0)) {
	    mp_mul_2d(&b, 1, &b);
	    if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		++digit;
		if (digit == 10) {
		    *s++ = '9';
		    s = BumpUp(s, retval, &k);
		    break;
		}
	    }
	    *s++ = '0' + digit;
	    break;
	}

	/*
	 * Does the current digit leave us with a remainder large enough
	 * to commit to rounding up to the next higher digit?
	 */

	if (ShouldBankerRoundUpToNext(&b, &mminus, &S, convType,
				      dPtr->w.word1 & 1, &temp)) {
	    ++digit;
	    if (digit == 10) {
		*s++ = '9';
		s = BumpUp(s, retval, &k);
		break;
	    }
	    *s++ = '0' + digit;
	    break;
	}


	/* Have we converted all the requested digits? */


	*s++ = '0' + digit;
	if (i == ilim) {
	    mp_mul_2d(&b, 1, &b);
	    if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		s = BumpUp(s, retval, &k);
	    }
	    break;
	}


	/* Advance to the next digit */


	if (s5 > 0) {

	    /* Can possibly shorten the denominator */


	    mp_mul_2d(&b, 1, &b);
	    mp_mul_2d(&mminus, 1, &mminus);
	    if (m2plus > m2minus) {
		mp_mul_2d(&mplus, 1, &mplus);
	    }
	    mp_div_d(&S, 5, &S, NULL);
	    --s5;

	    /*
	     * IDEA: It might possibly be a win to fall back to
	     *       int64 arithmetic here if S < 2**64/10. But it's
	     *       a win only for a fairly narrow range of magnitudes
	     *       so perhaps not worth bothering. We already know that
	     *       we shorten the denominator by at least 1 mp_digit, perhaps
	     *       2. as we do the conversion for 17 digits of significance.
	     * Possible savings:
	     * 10**26   1 trip through loop before fallback possible
	     * 10**27   1 trip
	     * 10**28   2 trips
	     * 10**29   3 trips
	     * 10**30   4 trips
	     * 10**31   5 trips
	     * 10**32   6 trips
	     * 10**33   7 trips
	     * 10**34   8 trips
	     * 10**35   9 trips
	     * 10**36  10 trips
	     * 10**37  11 trips
	     * 10**38  12 trips
	     * 10**39  13 trips
	     * 10**40  14 trips
	     * 10**41  15 trips
	     * 10**42  16 trips
	     * thereafter  no gain.
	     */
	} else {
	    mp_mul_d(&b, 10, &b);
	    mp_mul_d(&mminus, 10, &mminus);
	    if (m2plus > m2minus) {
		mp_mul_2d(&mplus, 10, &mplus);
	    }
	}

	++i;
    }


    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &temp, &dig, &S, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;

}

/*
 *-----------------------------------------------------------------------------
 *
 * StrictBignumConversion --
 *
 *	Convert a floating point number to a fixed-length digit string
 *	using the multiprecision method.
 *
 * Results:
 *	Returns the string of digits.
 *
 * Side effects:
 *	Stores the position of the decimal point in *decpt.
 *	Stores a pointer to the end of the number in *endPtr.
 *
 *-----------------------------------------------------------------------------
 */

inline static char*
StrictBignumConversion(Double* dPtr,
				/* Original number being converted */
		       int convType,
				/* Conversion type */
		       Tcl_WideUInt bw,
				/* Integer significand and exponent */
		       int b2,	/* Scale factor for the significand */
		       int s2, int s5,
				/* Scale factors for denominator */
		       int k,	/* Guessed position of the decimal point */
		       int len,	/* Size of the digit buffer to allocate */
		       int ilim,
				/* Number of digits to convert if b >= s */
		       int ilim1,
				/* Number of digits to convert if b < s */
		       int* decpt,
				/* OUTPUT: Position of the decimal point */
		       char** endPtr)
				/* OUTPUT: Pointer to the end of the number */
{
    char* retval = ckalloc(len+1);
				/* Buffer of digits to return */
    char* s = retval;		/* Cursor in the return value */
    mp_int b;			/* Numerator of the result */
    mp_int S;			/* Denominator of the result */
    mp_int dig;			/* Current digit of the result */
    int digit;			/* Current digit of the result */
    mp_int temp;		/* Work area */
    int g;			/* Size of the current digit groun */
    int i, j;

    /*
     * b = bw * 2**b2 * 5**b5
     * S = 2**s2 * 5*s5
     */

    mp_init_multi(&temp, &dig, NULL);
    TclBNInitBignumFromWideUInt(&b, bw);
    mp_mul_2d(&b, b2, &b);
    mp_init_set_int(&S, 1);
    MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);

    /*
     * Handle the case where we guess the position of the decimal point
     * wrong.
     */

    if (mp_cmp_mag(&b, &S) == MP_LT) {
	mp_mul_d(&b, 10, &b);
	ilim =ilim1;
	--k;
    }


    /* Convert the leading digit */


    i = 0;
    mp_div(&b, &S, &dig, &b);
    if (dig.used > 1 || dig.dp[0] >= 10) {
	Tcl_Panic("wrong digit!");
    }
    digit = dig.dp[0];


    /* Is a single digit all that was requested? */


    *s++ = '0' + digit;
    if (++i >= ilim) {
	mp_mul_2d(&b, 1, &b);
	if (ShouldBankerRoundUp(&b, &S, digit&1)) {
	    s = BumpUp(s, retval, &k);
	}
    } else {

	for (;;) {

	    /* Shift by a group of digits. */


	    g = ilim - i;
	    if (g > DIGIT_GROUP) {
		g = DIGIT_GROUP;
	    }
	    if (s5 >= g) {
		mp_div_d(&S, dpow5[g], &S, NULL);
		s5 -= g;
	    } else if (s5 > 0) {
		mp_div_d(&S, dpow5[s5], &S, NULL);
		mp_mul_d(&b, dpow5[g - s5], &b);
		s5 = 0;
	    } else {
		mp_mul_d(&b, dpow5[g], &b);
	    }
	    mp_mul_2d(&b, g, &b);

	    /*
	     * As with the shortening bignum conversion, it's possible at
	     * this point that we will have reduced the denominator to
	     * less than 2**64/10, at which point it would be possible to
	     * fall back to to int64 arithmetic. But the potential payoff
	     * is tremendously less - unless we're working in F format -
	     * because we know that three groups of digits will always
	     * suffice for %#.17e, the longest format that doesn't introduce
	     * empty precision.
	     */

	    /* Extract the next group of digits */


	    mp_div(&b, &S, &dig, &b);
	    if (dig.used > 1) {
		Tcl_Panic("wrong digit!");
	    }
	    digit = dig.dp[0];
	    for (j = g-1; j >= 0; --j) {
		int t = itens[j];

		*s++ = digit / t + '0';
		digit %= t;
	    }
	    i += g;


	    /* Have we converted all the requested digits? */


	    if (i == ilim) {
		mp_mul_2d(&b, 1, &b);
		if (ShouldBankerRoundUp(&b, &S, digit&1)) {
		    s = BumpUp(s, retval, &k);
		} else {
		    while (*--s == '0') {
			/* do nothing */
		    }
		    ++s;
		}
	    break;
	    }


	}

    }
    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &S, &temp, &dig, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;

}

/*
 *-----------------------------------------------------------------------------
 *
 * TclDoubleDigits --
 *
 *	Core of Tcl's conversion of double-precision floating point numbers
 *	to decimal.
 *
 * Results:
 *	Returns a newly-allocated string of digits.
 *
 * Side effects:
 *	Sets *decpt to the index of the character in the string before the
 *	place that the decimal point should go. If 'endPtr' is not NULL,
 *	sets endPtr to point to the terminating '\0' byte of the string.
 *	Sets *sign to 1 if a minus sign should be printed with the number,
 *	or 0 if a plus sign (or no sign) should appear.
 *
 * This function is a service routine that produces the string of digits
 * for floating-point-to-decimal conversion. It can do a number of things
 * according to the 'flags' argument. Valid values for 'flags' include:
 *	TCL_DD_SHORTEST - This is the default for floating point conversion
 *		if ::tcl_precision is 0. It constructs the shortest string
 *		of digits that will reconvert to the given number when scanned.
 *		For floating point numbers that are exactly between two
 *		decimal numbers, it resolves using the 'round to even' rule.
 *		With this value, the 'ndigits' parameter is ignored.
 *	TCL_DD_STEELE - This value is not recommended and may be removed
 *		in the future. It follows the conversion algorithm outlined
 *		in "How to Print Floating-Point Numbers Accurately" by
 *		Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90,
 *		pp. 112-126]. This rule has the effect of rendering 1e23
 *		as 9.9999999999999999e22 - which is a 'better' approximation
 *		in the sense that it will reconvert correctly even if
 *		a subsequent input conversion is 'round up' or 'round down'
 *		rather than 'round to nearest', but is surprising otherwise.
 *	TCL_DD_E_FORMAT - This value is used to prepare numbers for %e
 *		format conversion (or for default floating->string if
 *		tcl_precision is not 0). It constructs a string of at most
 *		'ndigits' digits, choosing the one that is closest to the
 *		given number (and resolving ties with 'round to even').
 *		It is allowed to return fewer than 'ndigits' if the number
 *		converts exactly; if the TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG
 *		is supplied instead, it also returns fewer digits if the
 *		shorter string will still reconvert to the given input number.
 *		In any case, strings of trailing zeroes are suppressed.
 *	TCL_DD_F_FORMAT - This value is used to prepare numbers for %f
 *		format conversion. It requests that conversion proceed until
 *		'ndigits' digits after the decimal point have been converted.
 *		It is possible for this format to result in a zero-length
 *		string if the number is sufficiently small. Again, it
 *		is permissible for TCL_DD_F_FORMAT to return fewer digits
 *		for a number that converts exactly, and changing the
 *		argument to TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow
 *		the routine also to return fewer digits if the shorter string
 *		will still reconvert without loss to the given input number.
 *		Strings of trailing zeroes are suppressed.
 *
 *	To any of these flags may be OR'ed TCL_DD_NO_QUICK; this flag
 *	requires all calculations to be done in exact arithmetic. Normally,
 *	E and F format with fewer than about 14 digits will be done with
 *	a quick floating point approximation and fall back on the exact
 *	arithmetic only if the input number is close enough to the
 *	midpoint between two decimal strings that more precision is needed
 *	to resolve which string is correct.
 *
 * The value stored in the 'decpt' argument on return may be negative
 * (indicating that the decimal point falls to the left of the string)
 * or greater than the length of the string.  In addition, the value -9999
 * is used as a sentinel to indicate that the string is one of the special
 * values "Infinity" and "NaN", and that no decimal point should be inserted.
 *
 *-----------------------------------------------------------------------------
 */

char*
TclDoubleDigits(double dv,	/* Number to convert */

		int ndigits,	/* Number of digits requested */
		int flags,	/* Conversion flags */
		int* decpt,	/* OUTPUT: Position of the decimal point */
		int* sign,	/* OUTPUT: 1 if the result is negative */
		char** endPtr)	/* OUTPUT: If not NULL, receives a pointer
				 *         to one character beyond the end
				 *         of the returned string */
{
    int convType = (flags & TCL_DD_CONVERSION_TYPE_MASK);
				/* Type of conversion being performed
				 * TCL_DD_SHORTEST0
				 * TCL_DD_STEELE0
				 * TCL_DD_E_FORMAT
				 * TCL_DD_F_FORMAT */
    Double d;			/* Union for deconstructing doubles */
    Tcl_WideUInt bw;		/* Integer significand */
    int be;			/* Power of 2 by which b must be multiplied */
    int bbits;			/* Number of bits needed to represent b */
    int denorm;			/* Flag == 1 iff the input number was
				 * denormalized */
    int k;			/* Estimate of floor(log10(d)) */
    int k_check;		/* Flag == 1 if d is near enough to a
				 * power of ten that k must be checked */
    int b2, b5, s2, s5;		/* Powers of 2 and 5 in the numerator and
				 * denominator of intermediate results */
    int ilim = -1, ilim1 = -1;	/* Number of digits to convert, and number
				 * to convert if log10(d) has been
				 * overestimated */
    char* retval;		/* Return value from this function */
    int i = -1;


    /* Put the input number into a union for bit-whacking */


    d.d = dv;

    /*
     * Handle the cases of negative numbers (by taking the absolute value:
     * this includes -Inf and -NaN!), infinity, Not a Number, and zero.
     */

    TakeAbsoluteValue(&d, sign);
    if ((d.w.word0 & EXP_MASK) == EXP_MASK) {
	return FormatInfAndNaN(&d, decpt, endPtr);
    }
    if (d.d == 0.0) {
	return FormatZero(decpt, endPtr);
    }

    /*
     * Unpack the floating point into a wide integer and an exponent.
     * Determine the number of bits that the big integer requires, and
     * compute a quick approximation (which may be one too high) of
     * ceil(log10(d.d)).
     */

    denorm = ((d.w.word0 & EXP_MASK) == 0);
    DoubleToExpAndSig(d.d, &bw, &be, &bbits);
    k = ApproximateLog10(bw, be, bbits);
    k = BetterLog10(d.d, k, &k_check);

    /* At this point, we have:
     *	  d is the number to convert.
     *    bw are significand and exponent: d == bw*2**be,
     *    bbits is the length of bw: 2**bbits-1 <= bw < 2**bbits
     *	  k is either ceil(log10(d)) or ceil(log10(d))+1. k_check is 0
     *      if we know that k is exactly ceil(log10(d)) and 1 if we need to
     *	    check.
     *    We want a rational number
     *      r = b * 10**(1-k) = bw * 2**b2 * 5**b5 / (2**s2 / 5**s5),
     *    with b2, b5, s2, s5 >= 0.  Note that the most significant decimal
     *    digit is floor(r) and that successive digits can be obtained
     *    by setting r <- 10*floor(r) (or b <= 10 * (b % S)).
     *    Find appropriate b2, b5, s2, s5.
     */

    ComputeScale(be, k, &b2, &b5, &s2, &s5);

    /*
     * Correct an incorrect caller-supplied 'ndigits'.
     * Also determine:
     *	i = The maximum number of decimal digits that will be returned in the
     *      formatted string.  This is k + 1 + ndigits for F format, 18 for
     *	    shortest and Steele, and ndigits for E format.
     *  ilim = The number of significant digits to convert if
     *         k has been guessed correctly. This is -1 for shortest and Steele
     *         (which stop when all significance has been lost), 'ndigits'
     *	       for E format, and 'k + 1 + ndigits' for F format.
     *  ilim1 = The minimum number of significant digits to convert if
     *	        k has been guessed 1 too high. This, too, is -1 for shortest
     *	        and Steele, and 'ndigits' for E format, but it's 'ndigits-1'
     *	        for F format.
     */

    SetPrecisionLimits(convType, k, &ndigits, &i, &ilim, &ilim1);

    /*
     * Try to do low-precision conversion in floating point rather
     * than resorting to expensive multiprecision arithmetic
     */

    if (ilim >= 0 && ilim <= QUICK_MAX && !(flags & TCL_DD_NO_QUICK)) {
	if ((retval = QuickConversion(d.d, k, k_check, flags,
				      i, ilim, ilim1,
				      decpt, endPtr)) != NULL) {

	    return retval;
	}
    }

    /*
     * For shortening conversions, determine the upper and lower bounds
     * for the remainder at which we can stop.
     *   m+ = (2**m2plus * 5**m5) / (2**s2 * 5**s5) is the limit on the
     *        high side, and
     *   m- = (2**m2minus * 5**m5) / (2**s2 * 5**s5) is the limit on the
     *        low side.
     *   We may need to increase s2 to put m2plus, m2minus, b2 over a
     *   common denominator.
     */

    if (flags & TCL_DD_SHORTEN_FLAG) {
	int m2minus = b2;
	int m2plus;
	int m5 = b5;
	int len = i;

	/*
	 * Find the quantity i so that (2**i*5**b5)/(2**s2*5**s5)
	 * is 1/2 unit in the least significant place of the floating
	 * point number.
	 */

	if (denorm) {
	    i = be + EXPONENT_BIAS + (FP_PRECISION-1);
	} else {
	    i = 1 + FP_PRECISION - bbits;
	}
	b2 += i;
	s2 += i;

	/*
	 * Reduce the fractions to lowest terms, since the above calculation
	 * may have left excess powers of 2 in numerator and denominator
	 */

	CastOutPowersOf2(&b2, &m2minus, &s2);

	/*
	 * In the special case where bw==1, the nearest floating point number
	 * to it on the low side is 1/4 ulp below it. Adjust accordingly.
	 */

	m2plus = m2minus;
	if (!denorm && bw == 1) {
	    ++b2;
	    ++s2;
	    ++m2plus;
	}

	if (s5+1 < N_LOG2POW5
	    && s2+1 + log2pow5[s5+1] <= 64) {
	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit
	     * word, then all our intermediate calculations can be done
	     * using exact 64-bit arithmetic with no need for expensive
	     * multiprecision operations. (This will be true for all numbers
	     * in the range [1.0e-3 .. 1.0e+24]).
	     */

	    return ShorteningInt64Conversion(&d, convType, bw, b2, b5,
					     m2plus, m2minus, m5,
					     s2, s5, k, len, ilim, ilim1,
					     decpt, endPtr);
	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */

	    if (s2 % DIGIT_BIT != 0) {
		int delta = DIGIT_BIT - (s2 % DIGIT_BIT);

		b2 += delta;
		m2plus += delta;
		m2minus += delta;
		s2 += delta;
	    }
	    return ShorteningBignumConversionPowD(&d, convType, bw, b2, b5,
						  m2plus, m2minus, m5,
						  s2/DIGIT_BIT, k, len,
						  ilim, ilim1, decpt, endPtr);
	} else {

	    /*
	     * Alas, there's no helpful special case; use full-up
	     * bignum arithmetic for the conversion
	     */

	    return ShorteningBignumConversion(&d, convType, bw,
					      b2, m2plus, m2minus,
					      s2, s5, k, len,
					      ilim, ilim1, decpt, endPtr);

	}

    } else {

	/* Non-shortening conversion */


	int len = i;


	/* Reduce numerator and denominator to lowest terms */


	if (b2 >= s2 && s2 > 0) {
	    b2 -= s2; s2 = 0;
	} else if (s2 >= b2 && b2 > 0) {
	    s2 -= b2; b2 = 0;
	}

	if (s5+1 < N_LOG2POW5
	    && s2+1 + log2pow5[s5+1] <= 64) {
	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit
	     * word, then all our intermediate calculations can be done
	     * using exact 64-bit arithmetic with no need for expensive
	     * multiprecision operations.
	     */

	    return StrictInt64Conversion(&d, convType, bw, b2, b5,
					 s2, s5, k, len, ilim, ilim1,
					 decpt, endPtr);

	} else if (s5 == 0) {
	    /*
	     * The denominator is a power of 2, so we can replace division
	     * by digit shifts. First we round up s2 to a multiple of
	     * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
	     * into a version of the comparison that's specialized for
	     * the 'power of mp_digit in the denominator' case.
	     */

	    if (s2 % DIGIT_BIT != 0) {
		int delta = DIGIT_BIT - (s2 % DIGIT_BIT);

		b2 += delta;
		s2 += delta;
	    }
	    return StrictBignumConversionPowD(&d, convType, bw, b2, b5,
					      s2/DIGIT_BIT, k, len,
					      ilim, ilim1, decpt, endPtr);
	} else {
	    /*
	     * There are no helpful special cases, but at least we know
	     * in advance how many digits we will convert. We can run the
	     * conversion in steps of DIGIT_GROUP digits, so as to
	     * have many fewer mp_int divisions.
	     */

	    return StrictBignumConversion(&d, convType, bw, b2, s2, s5,
					  k, len, ilim, ilim1, decpt, endPtr);
	}
    }
}


/*
 *----------------------------------------------------------------------
 *
 * TclInitDoubleConversion --
 *
 *	Initializes constants that are needed for conversions to and from
4501
4502
4503
4504
4505
4506
4507

4508
4509
4510
4511
4512
4513

4514
4515
4516
4517
4518
4519
4520
void
TclInitDoubleConversion(void)
{
    int i;
    int x;
    Tcl_WideUInt u;
    double d;

#ifdef IEEE_FLOATING_POINT
    union {
	double dv;
	Tcl_WideUInt iv;
    } bitwhack;
#endif

#if defined(__sgi) && defined(_COMPILER_VERSION)
    union fpc_csr mipsCR;

    mipsCR.fc_word = get_fpc_csr();
    mipsCR.fc_struct.flush = 0;
    set_fpc_csr(mipsCR.fc_word);
#endif







>






>







4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
void
TclInitDoubleConversion(void)
{
    int i;
    int x;
    Tcl_WideUInt u;
    double d;

#ifdef IEEE_FLOATING_POINT
    union {
	double dv;
	Tcl_WideUInt iv;
    } bitwhack;
#endif

#if defined(__sgi) && defined(_COMPILER_VERSION)
    union fpc_csr mipsCR;

    mipsCR.fc_word = get_fpc_csr();
    mipsCR.fc_struct.flush = 0;
    set_fpc_csr(mipsCR.fc_word);
#endif
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
    for (i = 0; i < maxpow10_wide; ++i) {
	pow10_wide[i] = u;
	u *= 10;
    }
    pow10_wide[i] = u;

    /*
     * Determine how many bits of precision a double has, and how many decimal
     * digits that represents.
     */

    if (frexp((double) FLT_RADIX, &log2FLT_RADIX) != 0.5) {
	Tcl_Panic("This code doesn't work on a decimal machine!");
    }
    log2FLT_RADIX--;
    mantBits = DBL_MANT_DIG * log2FLT_RADIX;
    d = 1.0;

    /*
     * Initialize a table of powers of ten that can be exactly represented in
     * a double.
     */

    x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log(5.0));
    if (x < MAXPOW) {
	mmaxpow = x;
    } else {
	mmaxpow = MAXPOW;







|
|










|
|







4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
    for (i = 0; i < maxpow10_wide; ++i) {
	pow10_wide[i] = u;
	u *= 10;
    }
    pow10_wide[i] = u;

    /*
     * Determine how many bits of precision a double has, and how many
     * decimal digits that represents.
     */

    if (frexp((double) FLT_RADIX, &log2FLT_RADIX) != 0.5) {
	Tcl_Panic("This code doesn't work on a decimal machine!");
    }
    log2FLT_RADIX--;
    mantBits = DBL_MANT_DIG * log2FLT_RADIX;
    d = 1.0;

    /*
     * Initialize a table of powers of ten that can be exactly represented
     * in a double.
     */

    x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log(5.0));
    if (x < MAXPOW) {
	mmaxpow = x;
    } else {
	mmaxpow = MAXPOW;
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
     * the significand of a double.
     */

    maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX)
	    + 0.5 * log(10.)) / log(10.));
    minDigits = (int) floor((DBL_MIN_EXP - DBL_MANT_DIG)
	    * log((double) FLT_RADIX) / log(10.));
    log10_DIGIT_MAX = (int) floor(MP_DIGIT_BIT * log(2.) / log(10.));

    /*
     * Nokia 770's software-emulated floating point is "middle endian": the
     * bytes within a 32-bit word are little-endian (like the native
     * integers), but the two words of a 'double' are presented most
     * significant word first.
     */

#ifdef IEEE_FLOATING_POINT
    bitwhack.dv = 1.000000238418579;
				/* 3ff0 0000 4000 0000 */
    if ((bitwhack.iv >> 32) == 0x3FF00000) {
	n770_fp = 0;
    } else if ((bitwhack.iv & 0xFFFFFFFF) == 0x3FF00000) {
	n770_fp = 1;
    } else {
	Tcl_Panic("unknown floating point word order on this machine");
    }
#endif
}








|











|

|







4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
     * the significand of a double.
     */

    maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX)
	    + 0.5 * log(10.)) / log(10.));
    minDigits = (int) floor((DBL_MIN_EXP - DBL_MANT_DIG)
	    * log((double) FLT_RADIX) / log(10.));
    log10_DIGIT_MAX = (int) floor(DIGIT_BIT * log(2.) / log(10.));

    /*
     * Nokia 770's software-emulated floating point is "middle endian": the
     * bytes within a 32-bit word are little-endian (like the native
     * integers), but the two words of a 'double' are presented most
     * significant word first.
     */

#ifdef IEEE_FLOATING_POINT
    bitwhack.dv = 1.000000238418579;
				/* 3ff0 0000 4000 0000 */
    if ((bitwhack.iv >> 32) == 0x3ff00000) {
	n770_fp = 0;
    } else if ((bitwhack.iv & 0xffffffff) == 0x3ff00000) {
	n770_fp = 1;
    } else {
	Tcl_Panic("unknown floating point word order on this machine");
    }
#endif
}

4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
{
    int i;

    ckfree((char *) pow10_wide);
    for (i=0; i<9; ++i) {
	mp_clear(pow5 + i);
    }
    for (i=0; i < 5; ++i) {
	mp_clear(pow5_13 + i);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitBignumFromDouble --
 *







<
<
<







4476
4477
4478
4479
4480
4481
4482



4483
4484
4485
4486
4487
4488
4489
{
    int i;

    ckfree((char *) pow10_wide);
    for (i=0; i<9; ++i) {
	mp_clear(pow5 + i);
    }



}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitBignumFromDouble --
 *
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
 *	it.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_InitBignumFromDouble(
    Tcl_Interp *interp,		/* For error message. */
    double d,			/* Number to convert. */
    mp_int *b)			/* Place to store the result. */
{
    double fract;
    int expt;

    /*
     * Infinite values can't convert to bignum.
     */







|
|
|







4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
 *	it.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_InitBignumFromDouble(
    Tcl_Interp *interp,		/* For error message */
    double d,			/* Number to convert */
    mp_int *b)			/* Place to store the result */
{
    double fract;
    int expt;

    /*
     * Infinite values can't convert to bignum.
     */
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
     * We need a 'mantBits'-bit significand.  Determine what shift will
     * give us that.
     */

    bits = mp_count_bits(a);
    if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
	errno = ERANGE;
	if (mp_isneg(a)) {
	    return -HUGE_VAL;
	} else {
	    return HUGE_VAL;
	}
    }
    shift = mantBits - bits;

    /*
     * If shift > 0, shift the significand left by the requisite number of
     * bits.  If shift == 0, the significand is already exactly 'mantBits'







|
|

|







4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
     * We need a 'mantBits'-bit significand.  Determine what shift will
     * give us that.
     */

    bits = mp_count_bits(a);
    if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
	errno = ERANGE;
	if (a->sign == MP_ZPOS) {
	    return HUGE_VAL;
	} else {
	    return -HUGE_VAL;
	}
    }
    shift = mantBits - bits;

    /*
     * If shift > 0, shift the significand left by the requisite number of
     * bits.  If shift == 0, the significand is already exactly 'mantBits'
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836

	    /*
	     * Round to even
	     */

	    mp_div_2d(a, -shift, &b, NULL);
	    if (mp_isodd(&b)) {
		if (mp_isneg(&b)) {
		    mp_sub_d(&b, 1, &b);
		} else {
		    mp_add_d(&b, 1, &b);
		}
	    }
	} else {

	    /*
	     * Ordinary rounding
	     */

	    mp_div_2d(a, -1-shift, &b, NULL);
	    if (mp_isneg(&b)) {
		mp_sub_d(&b, 1, &b);
	    } else {
		mp_add_d(&b, 1, &b);
	    }
	    mp_div_2d(&b, 1, &b, NULL);
	}
    }

    /*
     * Accumulate the result, one mp_digit at a time.
     */

    r = 0.0;
    for (i=b.used-1 ; i>=0 ; --i) {
	r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
    }
    mp_clear(&b);

    /*
     * Scale the result to the correct number of bits.
     */

    r = ldexp(r, bits - mantBits);

    /*
     * Return the result with the appropriate sign.
     */

    if (mp_isneg(a)) {
	return -r;
    } else {
	return r;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclCeil --
 *
 *	Computes the smallest floating point number that is at least the
 *	mp_int argument.
 *
 * Results:
 *	Returns the floating point number.
 *
 *----------------------------------------------------------------------
 */

double
TclCeil(
    mp_int *a)			/* Integer to convert. */
{
    double r = 0.0;







|
|

|









|
|

|











|













|
|

|


|

|









|







4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676

	    /*
	     * Round to even
	     */

	    mp_div_2d(a, -shift, &b, NULL);
	    if (mp_isodd(&b)) {
		if (b.sign == MP_ZPOS) {
		    mp_add_d(&b, 1, &b);
		} else {
		    mp_sub_d(&b, 1, &b);
		}
	    }
	} else {

	    /*
	     * Ordinary rounding
	     */

	    mp_div_2d(a, -1-shift, &b, NULL);
	    if (b.sign == MP_ZPOS) {
		mp_add_d(&b, 1, &b);
	    } else {
		mp_sub_d(&b, 1, &b);
	    }
	    mp_div_2d(&b, 1, &b, NULL);
	}
    }

    /*
     * Accumulate the result, one mp_digit at a time.
     */

    r = 0.0;
    for (i=b.used-1 ; i>=0 ; --i) {
	r = ldexp(r, DIGIT_BIT) + b.dp[i];
    }
    mp_clear(&b);

    /*
     * Scale the result to the correct number of bits.
     */

    r = ldexp(r, bits - mantBits);

    /*
     * Return the result with the appropriate sign.
     */

    if (a->sign == MP_ZPOS) {
	return r;
    } else {
	return -r;
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * TclCeil --
 *
 *	Computes the smallest floating point number that is at least the
 *	mp_int argument.
 *
 * Results:
 *	Returns the floating point number.
 *
 *-----------------------------------------------------------------------------
 */

double
TclCeil(
    mp_int *a)			/* Integer to convert. */
{
    double r = 0.0;
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
	    } else {
		mp_copy(a, &b);
	    }
	    if (!exact) {
		mp_add_d(&b, 1, &b);
	    }
	    for (i=b.used-1 ; i>=0 ; --i) {
		r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
	    }
	    r = ldexp(r, bits - mantBits);
	}
    }
    mp_clear(&b);
    return r;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFloor --
 *
 *	Computes the largest floating point number less than or equal to the
 *	mp_int argument.
 *
 * Results:
 *	Returns the floating point value.
 *
 *----------------------------------------------------------------------
 */

double
TclFloor(
    mp_int *a)			/* Integer to convert. */
{
    double r = 0.0;







|







|

|



|
|




|







4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
	    } else {
		mp_copy(a, &b);
	    }
	    if (!exact) {
		mp_add_d(&b, 1, &b);
	    }
	    for (i=b.used-1 ; i>=0 ; --i) {
		r = ldexp(r, DIGIT_BIT) + b.dp[i];
	    }
	    r = ldexp(r, bits - mantBits);
	}
    }
    mp_clear(&b);
    return r;
}

/*
 *-----------------------------------------------------------------------------
 *
 * TclFloor --
 *
 *	Computes the largest floating point number less than or equal to
 *	the mp_int argument.
 *
 * Results:
 *	Returns the floating point value.
 *
 *-----------------------------------------------------------------------------
 */

double
TclFloor(
    mp_int *a)			/* Integer to convert. */
{
    double r = 0.0;
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
		mp_mul_2d(a, shift, &b);
	    } else if (shift < 0) {
		mp_div_2d(a, -shift, &b, NULL);
	    } else {
		mp_copy(a, &b);
	    }
	    for (i=b.used-1 ; i>=0 ; --i) {
		r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
	    }
	    r = ldexp(r, bits - mantBits);
	}
    }
    mp_clear(&b);
    return r;
}







|







4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
		mp_mul_2d(a, shift, &b);
	    } else if (shift < 0) {
		mp_div_2d(a, -shift, &b, NULL);
	    } else {
		mp_copy(a, &b);
	    }
	    for (i=b.used-1 ; i>=0 ; --i) {
		r = ldexp(r, DIGIT_BIT) + b.dp[i];
	    }
	    r = ldexp(r, bits - mantBits);
	}
    }
    mp_clear(&b);
    return r;
}
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
 *	Stores the exponent of two in 'machexp'.
 *
 *----------------------------------------------------------------------
 */

static double
BignumToBiasedFrExp(
    mp_int *a,		/* Integer to convert. */
    int *machexp)		/* Power of two. */
{
    mp_int b;
    int bits;
    int shift;
    int i;
    double r;








|
|







4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
 *	Stores the exponent of two in 'machexp'.
 *
 *----------------------------------------------------------------------
 */

static double
BignumToBiasedFrExp(
    mp_int *a,			/* Integer to convert */
    int *machexp)		/* Power of two */
{
    mp_int b;
    int bits;
    int shift;
    int i;
    double r;

4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994

    /*
     * Accumulate the result, one mp_digit at a time.
     */

    r = 0.0;
    for (i=b.used-1; i>=0; --i) {
	r = ldexp(r, MP_DIGIT_BIT) + b.dp[i];
    }
    mp_clear(&b);

    /*
     * Return the result with the appropriate sign.
     */

    *machexp = bits - mantBits + 2;
    return (mp_isneg(a) ? -r : r);
}

/*
 *----------------------------------------------------------------------
 *
 * Pow10TimesFrExp --
 *







|








|







4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834

    /*
     * Accumulate the result, one mp_digit at a time.
     */

    r = 0.0;
    for (i=b.used-1; i>=0; --i) {
	r = ldexp(r, DIGIT_BIT) + b.dp[i];
    }
    mp_clear(&b);

    /*
     * Return the result with the appropriate sign.
     */

    *machexp = bits - mantBits + 2;
    return ((a->sign == MP_ZPOS) ? r : -r);
}

/*
 *----------------------------------------------------------------------
 *
 * Pow10TimesFrExp --
 *
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
 * though 'fraction*10**(machexp+exponent)' might overflow.
 *
 *----------------------------------------------------------------------
 */

static double
Pow10TimesFrExp(
    int exponent,		/* Power of 10 to multiply by. */
    double fraction,		/* Significand of multiplicand. */
    int *machexp)		/* On input, exponent of multiplicand. On
				 * output, exponent of result. */
{
    int i, j;
    int expt = *machexp;
    double retval = fraction;

    if (exponent > 0) {
	/*
	 * Multiply by 10**exponent.
	 */

	retval = frexp(retval * pow10vals[exponent&0xF], &j);
	expt += j;
	for (i=4; i<9; ++i) {
	    if (exponent & (1<<i)) {
		retval = frexp(retval * pow_10_2_n[i], &j);
		expt += j;
	    }
	}
    } else if (exponent < 0) {
	/*
	 * Divide by 10**-exponent.
	 */

	retval = frexp(retval / pow10vals[(-exponent) & 0xF], &j);
	expt += j;
	for (i=4; i<9; ++i) {
	    if ((-exponent) & (1<<i)) {
		retval = frexp(retval / pow_10_2_n[i], &j);
		expt += j;
	    }
	}







|
|









|


|









|


|







4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
 * though 'fraction*10**(machexp+exponent)' might overflow.
 *
 *----------------------------------------------------------------------
 */

static double
Pow10TimesFrExp(
    int exponent,	 	/* Power of 10 to multiply by */
    double fraction,		/* Significand of multiplicand */
    int *machexp)		/* On input, exponent of multiplicand. On
				 * output, exponent of result. */
{
    int i, j;
    int expt = *machexp;
    double retval = fraction;

    if (exponent > 0) {
	/*
	 * Multiply by 10**exponent
	 */

	retval = frexp(retval * pow10vals[exponent&0xf], &j);
	expt += j;
	for (i=4; i<9; ++i) {
	    if (exponent & (1<<i)) {
		retval = frexp(retval * pow_10_2_n[i], &j);
		expt += j;
	    }
	}
    } else if (exponent < 0) {
	/*
	 * Divide by 10**-exponent
	 */

	retval = frexp(retval / pow10vals[(-exponent) & 0xf], &j);
	expt += j;
	for (i=4; i<9; ++i) {
	    if ((-exponent) & (1<<i)) {
		retval = frexp(retval / pow_10_2_n[i], &j);
		expt += j;
	    }
	}
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
}

/*
 *----------------------------------------------------------------------
 *
 * Nokia770Twiddle --
 *
 *	Transpose the two words of a number for Nokia 770 floating point
 *	handling.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideUInt
Nokia770Twiddle(
    Tcl_WideUInt w)		/* Number to transpose. */
{
    return (((w >> 32) & 0xFFFFFFFF) | (w << 32));
}

/*
 *----------------------------------------------------------------------
 *
 * TclNokia770Doubles --
 *
 *	Transpose the two words of a number for Nokia 770 floating point
 *	handling.
 *
 *----------------------------------------------------------------------
 */

int
TclNokia770Doubles(void)
{







|
|






|

|







|
|







4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
}

/*
 *----------------------------------------------------------------------
 *
 * Nokia770Twiddle --
 *
 * 	Transpose the two words of a number for Nokia 770 floating
 *	point handling.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideUInt
Nokia770Twiddle(
    Tcl_WideUInt w)		/* Number to transpose */
{
    return (((w >> 32) & 0xffffffff) | (w << 32));
}

/*
 *----------------------------------------------------------------------
 *
 * TclNokia770Doubles --
 *
 * 	Transpose the two words of a number for Nokia 770 floating
 *	point handling.
 *
 *----------------------------------------------------------------------
 */

int
TclNokia770Doubles(void)
{

Changes to generic/tclStringObj.c.

1115
1116
1117
1118
1119
1120
1121
1122





1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
				 * the object. */
    const char *ellipsis)	/* Ellipsis marker string, appended to the
				 * object to indicate not all available bytes
				 * at "bytes" were appended. */
{
    String *stringPtr;
    int toCopy = 0;
    int eLen = 0;






    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    if (length == 0) {
	return;
    }
    if (limit <= 0) {
	return;
    }

    if (length <= limit) {
	toCopy = length;
    } else {
	if (ellipsis == NULL) {
	    ellipsis = "...";
	}
	eLen = strlen(ellipsis);
	while (eLen > limit) {
	    eLen = TclUtfPrev(ellipsis+eLen, ellipsis) - ellipsis;
	}

	toCopy = TclUtfPrev(bytes+limit+1-eLen, bytes) - bytes;
    }

    /*
     * If objPtr has a valid Unicode rep, then append the Unicode conversion
     * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to
     * objPtr's string rep.
     */

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
    }

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode != 0) {
	AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
    } else {
	AppendUtfToUtfRep(objPtr, bytes, toCopy);
    }

    if (length <= limit) {
	return;
    }

    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode != 0) {
	AppendUtfToUnicodeRep(objPtr, ellipsis, eLen);
    } else {
	AppendUtfToUtfRep(objPtr, ellipsis, eLen);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppendToObj --







|
>
>
>
>
>







<
<
<







<
<
<
<
|
|








<
<
<
<
<













|

|







1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134



1135
1136
1137
1138
1139
1140
1141




1142
1143
1144
1145
1146
1147
1148
1149
1150
1151





1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
				 * the object. */
    const char *ellipsis)	/* Ellipsis marker string, appended to the
				 * object to indicate not all available bytes
				 * at "bytes" were appended. */
{
    String *stringPtr;
    int toCopy = 0;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
    }

    SetStringFromAny(NULL, objPtr);

    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    if (length == 0) {
	return;
    }




    if (length <= limit) {
	toCopy = length;
    } else {
	if (ellipsis == NULL) {
	    ellipsis = "...";
	}




	toCopy = (bytes == NULL) ? limit
		: Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
    }

    /*
     * If objPtr has a valid Unicode rep, then append the Unicode conversion
     * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to
     * objPtr's string rep.
     */






    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode != 0) {
	AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
    } else {
	AppendUtfToUtfRep(objPtr, bytes, toCopy);
    }

    if (length <= limit) {
	return;
    }

    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode != 0) {
	AppendUtfToUnicodeRep(objPtr, ellipsis, -1);
    } else {
	AppendUtfToUtfRep(objPtr, ellipsis, -1);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppendToObj --
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
	}

	case 'u':
	    if (useBig) {
		msg = "unsigned bignum format is invalid";
		goto errorMsg;
	    }
	    /* FALLTHRU */
	case 'd':
	case 'o':
	case 'x':
	case 'X': {
	    short int s = 0;	/* Silence compiler warning; only defined and
				 * used when useShort is true. */
	    long l;







<







2066
2067
2068
2069
2070
2071
2072

2073
2074
2075
2076
2077
2078
2079
	}

	case 'u':
	    if (useBig) {
		msg = "unsigned bignum format is invalid";
		goto errorMsg;
	    }

	case 'd':
	case 'o':
	case 'x':
	case 'X': {
	    short int s = 0;	/* Silence compiler warning; only defined and
				 * used when useShort is true. */
	    long l;
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
	    } else if (useWide) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, CHAR_BIT*sizeof(Tcl_WideInt), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    Tcl_GetWideIntFromObj(NULL, objPtr, &w);
		    Tcl_DecrRefCount(objPtr);
		}
		isNegative = (w < (Tcl_WideInt)0);
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, CHAR_BIT * sizeof(long), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    TclGetLongFromObj(NULL, objPtr, &l);
		    Tcl_DecrRefCount(objPtr);
		} else {
		    l = Tcl_WideAsLong(w);
		}







|













|







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
	    } else if (useWide) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    Tcl_GetWideIntFromObj(NULL, objPtr, &w);
		    Tcl_DecrRefCount(objPtr);
		}
		isNegative = (w < (Tcl_WideInt)0);
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
		    Tcl_Obj *objPtr;

		    if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
			goto error;
		    }
		    mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
		    objPtr = Tcl_NewBignumObj(&big);
		    Tcl_IncrRefCount(objPtr);
		    TclGetLongFromObj(NULL, objPtr, &l);
		    Tcl_DecrRefCount(objPtr);
		} else {
		    l = Tcl_WideAsLong(w);
		}
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273

		    bits = uw;
		    while (uw) {
			numDigits++;
			uw /= base;
		    }
		} else if (useBig && big.used) {
		    int leftover = (big.used * MP_DIGIT_BIT) % numBits;
		    mp_digit mask = (~(mp_digit)0) << (MP_DIGIT_BIT-leftover);

		    numDigits = 1 +
			    (((Tcl_WideInt)big.used * MP_DIGIT_BIT) / numBits);
		    while ((mask & big.dp[big.used-1]) == 0) {
			numDigits--;
			mask >>= numBits;
		    }
		    if (numDigits > INT_MAX) {
			msg = overflow;
			goto errorMsg;







|
|


|







2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

		    bits = uw;
		    while (uw) {
			numDigits++;
			uw /= base;
		    }
		} else if (useBig && big.used) {
		    int leftover = (big.used * DIGIT_BIT) % numBits;
		    mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover);

		    numDigits = 1 +
			    (((Tcl_WideInt)big.used * DIGIT_BIT) / numBits);
		    while ((mask & big.dp[big.used-1]) == 0) {
			numDigits--;
			mask >>= numBits;
		    }
		    if (numDigits > INT_MAX) {
			msg = overflow;
			goto errorMsg;
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
		bytes = TclGetString(pure);
		toAppend = length = (int)numDigits;
		while (numDigits--) {
		    int digitOffset;

		    if (useBig && big.used) {
			if (index < big.used && (size_t) shift <
				CHAR_BIT*sizeof(Tcl_WideUInt) - MP_DIGIT_BIT) {
			    bits |= (((Tcl_WideUInt)big.dp[index++]) <<shift);
			    shift += MP_DIGIT_BIT;
			}
			shift -= numBits;
		    }
		    digitOffset = (int) (bits % base);
		    if (digitOffset > 9) {
			bytes[numDigits] = 'a' + digitOffset - 10;
		    } else {







|

|







2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
		bytes = TclGetString(pure);
		toAppend = length = (int)numDigits;
		while (numDigits--) {
		    int digitOffset;

		    if (useBig && big.used) {
			if (index < big.used && (size_t) shift <
				CHAR_BIT*sizeof(Tcl_WideUInt) - DIGIT_BIT) {
			    bits |= (((Tcl_WideUInt)big.dp[index++]) <<shift);
			    shift += DIGIT_BIT;
			}
			shift -= numBits;
		    }
		    digitOffset = (int) (bits % base);
		    if (digitOffset > 9) {
			bytes[numDigits] = 'a' + digitOffset - 10;
		    } else {
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596

		/*
		 * Within that buffer, we trim both ends if needed so that we
		 * copy only whole characters, and avoid copying any partial
		 * multi-byte characters.
		 */

		q = TclUtfPrev(end, bytes);
		if (!Tcl_UtfCharComplete(q, (int)(end - q))) {
		    end = q;
		}

		q = bytes + TCL_UTF_MAX;
		while ((bytes < end) && (bytes < q)
			&& ((*bytes & 0xC0) == 0x80)) {







|







2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588

		/*
		 * Within that buffer, we trim both ends if needed so that we
		 * copy only whole characters, and avoid copying any partial
		 * multi-byte characters.
		 */

		q = Tcl_UtfPrev(end, bytes);
		if (!Tcl_UtfCharComplete(q, (int)(end - q))) {
		    end = q;
		}

		q = bytes + TCL_UTF_MAX;
		while ((bytes < end) && (bytes < q)
			&& ((*bytes & 0xC0) == 0x80)) {
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
	    /* TODO: support for wide (and bignum?) arguments */
	    case 'l':
		size = 1;
		p++;
		break;
	    case 'h':
		size = -1;
		/* FALLTHRU */
	    default:
		p++;
	    }
	} while (seekingConversion);
    }
    TclListObjGetElements(NULL, list, &objc, &objv);
    code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv);







<







2640
2641
2642
2643
2644
2645
2646

2647
2648
2649
2650
2651
2652
2653
	    /* TODO: support for wide (and bignum?) arguments */
	    case 'l':
		size = 1;
		p++;
		break;
	    case 'h':
		size = -1;

	    default:
		p++;
	    }
	} while (seekingConversion);
    }
    TclListObjGetElements(NULL, list, &objc, &objv);
    code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv);

Changes to generic/tclStubInit.c.

1
2
3
4
5
6
7
8
/*
 * tclStubInit.c --
 *
 *	This file contains the initializers for the Tcl stub vectors.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
|







1
2
3
4
5
6
7
8
/* 
 * tclStubInit.c --
 *
 *	This file contains the initializers for the Tcl stub vectors.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#undef Tcl_FindHashEntry
#undef Tcl_CreateHashEntry
#undef TclpGetPid
#undef TclSockMinimumBuffers
#undef TclWinGetServByName
#undef TclWinGetSockOpt
#undef TclWinSetSockOpt
#define TclStaticPackage Tcl_StaticPackage
#define TclUnusedStubEntry NULL

/*
 * Keep a record of the original Notifier procedures, created in the
 * same compilation unit as the stub tables so we can later do reliable,
 * portable comparisons to see whether a Tcl_SetNotifier() call swapped
 * new routines into the stub table.







<







32
33
34
35
36
37
38

39
40
41
42
43
44
45
#undef Tcl_FindHashEntry
#undef Tcl_CreateHashEntry
#undef TclpGetPid
#undef TclSockMinimumBuffers
#undef TclWinGetServByName
#undef TclWinGetSockOpt
#undef TclWinSetSockOpt

#define TclUnusedStubEntry NULL

/*
 * Keep a record of the original Notifier procedures, created in the
 * same compilation unit as the stub tables so we can later do reliable,
 * portable comparisons to see whether a Tcl_SetNotifier() call swapped
 * new routines into the stub table.
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
    TclDbDumpActiveObjects, /* 243 */
    NULL, /* 244 */
    NULL, /* 245 */
    NULL, /* 246 */
    NULL, /* 247 */
    NULL, /* 248 */
    TclDoubleDigits, /* 249 */
    NULL, /* 250 */
    TclRegisterLiteral, /* 251 */
    NULL, /* 252 */
    NULL, /* 253 */
    NULL, /* 254 */
    NULL, /* 255 */
    NULL, /* 256 */
    TclStaticPackage, /* 257 */
    NULL, /* 258 */
    NULL, /* 259 */
    NULL, /* 260 */
    TclUnusedStubEntry, /* 261 */
};

TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    NULL,
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    TclGetAndDetachPids, /* 0 */







<
<
<
<
<
<
<
<
<
<
<
<







546
547
548
549
550
551
552












553
554
555
556
557
558
559
    TclDbDumpActiveObjects, /* 243 */
    NULL, /* 244 */
    NULL, /* 245 */
    NULL, /* 246 */
    NULL, /* 247 */
    NULL, /* 248 */
    TclDoubleDigits, /* 249 */












};

TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    NULL,
#if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    TclGetAndDetachPids, /* 0 */
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    NULL,
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
    Tcl_WinUtfToTChar, /* 0 */
    Tcl_WinTCharToUtf, /* 1 */
    NULL, /* 2 */
    TclUnusedStubEntry, /* 3 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_MacOSXOpenBundleResources, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */
    TclUnusedStubEntry, /* 2 */
#endif /* MACOSX */
};

TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    NULL,
    TclBN_epoch, /* 0 */







<
<




<







655
656
657
658
659
660
661


662
663
664
665

666
667
668
669
670
671
672

TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    NULL,
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
    Tcl_WinUtfToTChar, /* 0 */
    Tcl_WinTCharToUtf, /* 1 */


#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_MacOSXOpenBundleResources, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */

#endif /* MACOSX */
};

TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    NULL,
    TclBN_epoch, /* 0 */
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
    TclBN_s_mp_add, /* 57 */
    TclBN_s_mp_mul_digs, /* 58 */
    TclBN_s_mp_sqr, /* 59 */
    TclBN_s_mp_sub, /* 60 */
    TclBN_mp_init_set_int, /* 61 */
    TclBN_mp_set_int, /* 62 */
    TclBN_mp_cnt_lsb, /* 63 */
    NULL, /* 64 */
    NULL, /* 65 */
    NULL, /* 66 */
    NULL, /* 67 */
    NULL, /* 68 */
    NULL, /* 69 */
    NULL, /* 70 */
    NULL, /* 71 */
    NULL, /* 72 */
    NULL, /* 73 */
    NULL, /* 74 */
    NULL, /* 75 */
    NULL, /* 76 */
    NULL, /* 77 */
    NULL, /* 78 */
    NULL, /* 79 */
    TclUnusedStubEntry, /* 80 */
};

static TclStubHooks tclStubHooks = {
    &tclPlatStubs,
    &tclIntStubs,
    &tclIntPlatStubs
};







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







729
730
731
732
733
734
735

















736
737
738
739
740
741
742
    TclBN_s_mp_add, /* 57 */
    TclBN_s_mp_mul_digs, /* 58 */
    TclBN_s_mp_sqr, /* 59 */
    TclBN_s_mp_sub, /* 60 */
    TclBN_mp_init_set_int, /* 61 */
    TclBN_mp_set_int, /* 62 */
    TclBN_mp_cnt_lsb, /* 63 */

















};

static TclStubHooks tclStubHooks = {
    &tclPlatStubs,
    &tclIntStubs,
    &tclIntPlatStubs
};
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
    NULL, /* 623 */
    NULL, /* 624 */
    NULL, /* 625 */
    NULL, /* 626 */
    NULL, /* 627 */
    NULL, /* 628 */
    NULL, /* 629 */
    NULL, /* 630 */
    NULL, /* 631 */
    NULL, /* 632 */
    NULL, /* 633 */
    NULL, /* 634 */
    NULL, /* 635 */
    NULL, /* 636 */
    NULL, /* 637 */
    NULL, /* 638 */
    NULL, /* 639 */
    NULL, /* 640 */
    NULL, /* 641 */
    NULL, /* 642 */
    NULL, /* 643 */
    NULL, /* 644 */
    NULL, /* 645 */
    NULL, /* 646 */
    NULL, /* 647 */
    NULL, /* 648 */
    NULL, /* 649 */
    NULL, /* 650 */
    NULL, /* 651 */
    NULL, /* 652 */
    NULL, /* 653 */
    NULL, /* 654 */
    NULL, /* 655 */
    NULL, /* 656 */
    NULL, /* 657 */
    NULL, /* 658 */
    NULL, /* 659 */
    NULL, /* 660 */
    NULL, /* 661 */
    NULL, /* 662 */
    NULL, /* 663 */
    NULL, /* 664 */
    NULL, /* 665 */
    NULL, /* 666 */
    NULL, /* 667 */
    NULL, /* 668 */
    NULL, /* 669 */
    NULL, /* 670 */
    NULL, /* 671 */
    NULL, /* 672 */
    NULL, /* 673 */
    NULL, /* 674 */
    NULL, /* 675 */
    NULL, /* 676 */
    NULL, /* 677 */
    NULL, /* 678 */
    NULL, /* 679 */
    NULL, /* 680 */
    NULL, /* 681 */
    NULL, /* 682 */
    NULL, /* 683 */
    NULL, /* 684 */
    NULL, /* 685 */
    NULL, /* 686 */
    TclUnusedStubEntry, /* 687 */
};

/* !END!: Do not edit above this line. */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|



1394
1395
1396
1397
1398
1399
1400

























































1401
1402
1403
1404
    NULL, /* 623 */
    NULL, /* 624 */
    NULL, /* 625 */
    NULL, /* 626 */
    NULL, /* 627 */
    NULL, /* 628 */
    NULL, /* 629 */

























































    TclUnusedStubEntry, /* 630 */
};

/* !END!: Do not edit above this line. */

Changes to generic/tclStubLib.c.

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    int revision		/* Stubs table revision number from the
				 * header files */
) {
    int exact = 0;
    const char* packageName = "tcl::tommath";
    const char* errMsg = NULL;
    ClientData pkgClientData = NULL;
    const char* actualVersion =
	tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &pkgClientData);
    TclTomMathStubs* stubsPtr = (TclTomMathStubs*) pkgClientData;
    if (actualVersion == NULL) {
	return NULL;
    }
    if (pkgClientData == NULL) {
	errMsg = "missing stub table pointer";







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    int revision		/* Stubs table revision number from the
				 * header files */
) {
    int exact = 0;
    const char* packageName = "tcl::tommath";
    const char* errMsg = NULL;
    ClientData pkgClientData = NULL;
    const char* actualVersion = 
	tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &pkgClientData);
    TclTomMathStubs* stubsPtr = (TclTomMathStubs*) pkgClientData;
    if (actualVersion == NULL) {
	return NULL;
    }
    if (pkgClientData == NULL) {
	errMsg = "missing stub table pointer";

Changes to generic/tclTest.c.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    Tcl_AsyncHandler handler;	/* Tcl's token for the handler. */
    char *command;		/* Command to invoke when the handler is
				 * invoked. */
    struct TestAsyncHandler *nextPtr;
				/* Next is list of handlers. */
} TestAsyncHandler;

TCL_DECLARE_MUTEX(asyncTestMutex)

static TestAsyncHandler *firstHandler = NULL;

/*
 * The dynamic string below is used by the "testdstring" command to test the
 * dynamic string facilities.
 */







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    Tcl_AsyncHandler handler;	/* Tcl's token for the handler. */
    char *command;		/* Command to invoke when the handler is
				 * invoked. */
    struct TestAsyncHandler *nextPtr;
				/* Next is list of handlers. */
} TestAsyncHandler;

TCL_DECLARE_MUTEX(asyncTestMutex);

static TestAsyncHandler *firstHandler = NULL;

/*
 * The dynamic string below is used by the "testdstring" command to test the
 * dynamic string facilities.
 */
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
static Tcl_Trace cmdTrace;

/*
 * One of the following structures exists for each command created by
 * TestdelCmd:
 */

typedef struct {
    Tcl_Interp *interp;		/* Interpreter in which command exists. */
    char *deleteCmd;		/* Script to execute when command is deleted.
				 * Malloc'ed. */
} DelCmd;

/*
 * The following is used to keep track of an encoding that invokes a Tcl
 * command.
 */

typedef struct {
    Tcl_Interp *interp;
    char *toUtfCmd;
    char *fromUtfCmd;
} TclEncoding;

/*
 * The counter below is used to determine if the TestsaveresultFree routine







|










|







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
static Tcl_Trace cmdTrace;

/*
 * One of the following structures exists for each command created by
 * TestdelCmd:
 */

typedef struct DelCmd {
    Tcl_Interp *interp;		/* Interpreter in which command exists. */
    char *deleteCmd;		/* Script to execute when command is deleted.
				 * Malloc'ed. */
} DelCmd;

/*
 * The following is used to keep track of an encoding that invokes a Tcl
 * command.
 */

typedef struct TclEncoding {
    Tcl_Interp *interp;
    char *toUtfCmd;
    char *fromUtfCmd;
} TclEncoding;

/*
 * The counter below is used to determine if the TestsaveresultFree routine
147
148
149
150
151
152
153
154

155

156
157
158
159
160
161
162
163
164
165


166


167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

185
186

187


188
189
190
191
192
193
194
195
196
197
198

199


200

201
202
203
204
205
206
207
#ifdef TCL_THREADS
static Tcl_ThreadCreateType AsyncThreadProc(ClientData);
#endif
static void		CleanupTestSetassocdataTests(
			    ClientData clientData, Tcl_Interp *interp);
static void		CmdDelProc1(ClientData clientData);
static void		CmdDelProc2(ClientData clientData);
static Tcl_CmdProc	CmdProc1;

static Tcl_CmdProc	CmdProc2;

static void		CmdTraceDeleteProc(
			    ClientData clientData, Tcl_Interp *interp,
			    int level, char *command, Tcl_CmdProc *cmdProc,
			    ClientData cmdClientData, int argc,
			    char **argv);
static void		CmdTraceProc(ClientData clientData,
			    Tcl_Interp *interp, int level, char *command,
			    Tcl_CmdProc *cmdProc, ClientData cmdClientData,
			    int argc, char **argv);
static Tcl_CmdProc	CreatedCommandProc;


static Tcl_CmdProc	CreatedCommandProc2;


static void		DelCallbackProc(ClientData clientData,
			    Tcl_Interp *interp);
static Tcl_CmdProc	DelCmdProc;

static void		DelDeleteProc(ClientData clientData);
static void		EncodingFreeProc(ClientData clientData);
static int		EncodingToUtfProc(ClientData clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static int		EncodingFromUtfProc(ClientData clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static void		ExitProcEven(ClientData clientData);
static void		ExitProcOdd(ClientData clientData);
static Tcl_ObjCmdProc	GetTimesObjCmd;

static void		MainLoop(void);
static Tcl_CmdProc	NoopCmd;

static Tcl_ObjCmdProc	NoopObjCmd;


static int		ObjTraceProc(ClientData clientData,
			    Tcl_Interp *interp, int level, const char *command,
			    Tcl_Command commandToken, int objc,
			    Tcl_Obj *const objv[]);
static void		ObjTraceDeleteProc(ClientData clientData);
static void		PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr);
static void		SpecialFree(char *blockPtr);
static int		StaticInitProc(Tcl_Interp *interp);
#undef USE_OBSOLETE_FS_HOOKS
#ifdef USE_OBSOLETE_FS_HOOKS
static Tcl_CmdProc	TestaccessprocCmd;

static Tcl_CmdProc	TestopenfilechannelprocCmd;


static Tcl_CmdProc	TeststatprocCmd;

static int		PretendTclpAccess(const char *path, int mode);
static int		TestAccessProc1(const char *path, int mode);
static int		TestAccessProc2(const char *path, int mode);
static int		TestAccessProc3(const char *path, int mode);
static Tcl_Channel	PretendTclpOpenFileChannel(
			    Tcl_Interp *interp, const char *fileName,
			    const char *modeString, int permissions);







|
>
|
>









|
>
>
|
>
>


|
>














|
>

|
>
|
>
>










|
>
|
>
>
|
>







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#ifdef TCL_THREADS
static Tcl_ThreadCreateType AsyncThreadProc(ClientData);
#endif
static void		CleanupTestSetassocdataTests(
			    ClientData clientData, Tcl_Interp *interp);
static void		CmdDelProc1(ClientData clientData);
static void		CmdDelProc2(ClientData clientData);
static int		CmdProc1(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		CmdProc2(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static void		CmdTraceDeleteProc(
			    ClientData clientData, Tcl_Interp *interp,
			    int level, char *command, Tcl_CmdProc *cmdProc,
			    ClientData cmdClientData, int argc,
			    char **argv);
static void		CmdTraceProc(ClientData clientData,
			    Tcl_Interp *interp, int level, char *command,
			    Tcl_CmdProc *cmdProc, ClientData cmdClientData,
			    int argc, char **argv);
static int		CreatedCommandProc(
			    ClientData clientData, Tcl_Interp *interp,
			    int argc, const char **argv);
static int		CreatedCommandProc2(
			    ClientData clientData, Tcl_Interp *interp,
			    int argc, const char **argv);
static void		DelCallbackProc(ClientData clientData,
			    Tcl_Interp *interp);
static int		DelCmdProc(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static void		DelDeleteProc(ClientData clientData);
static void		EncodingFreeProc(ClientData clientData);
static int		EncodingToUtfProc(ClientData clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static int		EncodingFromUtfProc(ClientData clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static void		ExitProcEven(ClientData clientData);
static void		ExitProcOdd(ClientData clientData);
static int		GetTimesCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static void		MainLoop(void);
static int		NoopCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		NoopObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ObjTraceProc(ClientData clientData,
			    Tcl_Interp *interp, int level, const char *command,
			    Tcl_Command commandToken, int objc,
			    Tcl_Obj *const objv[]);
static void		ObjTraceDeleteProc(ClientData clientData);
static void		PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr);
static void		SpecialFree(char *blockPtr);
static int		StaticInitProc(Tcl_Interp *interp);
#undef USE_OBSOLETE_FS_HOOKS
#ifdef USE_OBSOLETE_FS_HOOKS
static int		TestaccessprocCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestopenfilechannelprocCmd(
			    ClientData dummy, Tcl_Interp *interp, int argc,
			    const char **argv);
static int		TeststatprocCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		PretendTclpAccess(const char *path, int mode);
static int		TestAccessProc1(const char *path, int mode);
static int		TestAccessProc2(const char *path, int mode);
static int		TestAccessProc3(const char *path, int mode);
static Tcl_Channel	PretendTclpOpenFileChannel(
			    Tcl_Interp *interp, const char *fileName,
			    const char *modeString, int permissions);
215
216
217
218
219
220
221
222
223
224
225

226

227

228

229

230

231

232

233


234

235


236


237


238


239
240
241
242

243

244


245

246


247


248

249

250

251

252

253

254

255


256

257

258


259
260
261
262
263
264
265

266

267

268

269


270


271


272


273


274
275
276


277
278

279

280

281

282


283
284
285

286

287

288


289


290

291

292


293


294
295
296
297
298
299


300


301
302
303
304
305
306
307

308





309
310
311
312

313

314

315

316

317
318
319
320
321
322
323

324
325

326
327
328
329

330
331
332
333


334
335


336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
			    Tcl_Interp *interp, const char *fileName,
			    const char *modeString, int permissions);
static int		PretendTclpStat(const char *path, struct stat *buf);
static int		TestStatProc1(const char *path, struct stat *buf);
static int		TestStatProc2(const char *path, struct stat *buf);
static int		TestStatProc3(const char *path, struct stat *buf);
#endif
static Tcl_CmdProc	TestasyncCmd;
static Tcl_ObjCmdProc	TestbytestringObjCmd;
static Tcl_ObjCmdProc	TeststringbytesObjCmd;
static Tcl_CmdProc	TestcmdinfoCmd;

static Tcl_CmdProc	TestcmdtokenCmd;

static Tcl_CmdProc	TestcmdtraceCmd;

static Tcl_CmdProc	TestconcatobjCmd;

static Tcl_CmdProc	TestcreatecommandCmd;

static Tcl_CmdProc	TestdcallCmd;

static Tcl_CmdProc	TestdelCmd;

static Tcl_CmdProc	TestdelassocdataCmd;

static Tcl_ObjCmdProc	TestdoubledigitsObjCmd;


static Tcl_CmdProc	TestdstringCmd;

static Tcl_ObjCmdProc	TestencodingObjCmd;


static Tcl_ObjCmdProc	TestevalexObjCmd;


static Tcl_ObjCmdProc	TestevalobjvObjCmd;


static Tcl_ObjCmdProc	TesteventObjCmd;


static int		TesteventProc(Tcl_Event *event, int flags);
static int		TesteventDeleteProc(Tcl_Event *event,
			    ClientData clientData);
static Tcl_CmdProc	TestexithandlerCmd;

static Tcl_CmdProc	TestexprlongCmd;

static Tcl_ObjCmdProc	TestexprlongobjCmd;


static Tcl_CmdProc	TestexprdoubleCmd;

static Tcl_ObjCmdProc	TestexprdoubleobjCmd;


static Tcl_ObjCmdProc	TestexprparserObjCmd;


static Tcl_CmdProc	TestexprstringCmd;

static Tcl_ObjCmdProc	TestfileCmd;

static Tcl_ObjCmdProc	TestfilelinkCmd;

static Tcl_CmdProc	TestfeventCmd;

static Tcl_CmdProc	TestgetassocdataCmd;

static Tcl_CmdProc	TestgetintCmd;

static Tcl_CmdProc	TestgetplatformCmd;

static Tcl_ObjCmdProc	TestgetvarfullnameCmd;


static Tcl_CmdProc	TestinterpdeleteCmd;

static Tcl_CmdProc	TestlinkCmd;

static Tcl_ObjCmdProc	TestlocaleCmd;


static int		TestMathFunc(ClientData clientData,
			    Tcl_Interp *interp, Tcl_Value *args,
			    Tcl_Value *resultPtr);
static int		TestMathFunc2(ClientData clientData,
			    Tcl_Interp *interp, Tcl_Value *args,
			    Tcl_Value *resultPtr);
static Tcl_CmdProc	TestmainthreadCmd;

static Tcl_CmdProc	TestsetmainloopCmd;

static Tcl_CmdProc	TestexitmainloopCmd;

static Tcl_CmdProc	TestpanicCmd;

static Tcl_ObjCmdProc	TestparserObjCmd;


static Tcl_ObjCmdProc	TestparsevarObjCmd;


static Tcl_ObjCmdProc	TestparsevarnameObjCmd;


static Tcl_ObjCmdProc	TestregexpObjCmd;


static Tcl_ObjCmdProc	TestreturnObjCmd;


static void		TestregexpXflags(const char *string,
			    int length, int *cflagsPtr, int *eflagsPtr);
static Tcl_ObjCmdProc	TestsaveresultCmd;


static void		TestsaveresultFree(char *blockPtr);
static Tcl_CmdProc	TestsetassocdataCmd;

static Tcl_CmdProc	TestsetCmd;

static Tcl_CmdProc	Testset2Cmd;

static Tcl_CmdProc	TestseterrorcodeCmd;

static Tcl_ObjCmdProc	TestsetobjerrorcodeCmd;


static Tcl_CmdProc	TestsetplatformCmd;
static Tcl_ObjCmdProc	TestsizeCmd;
static Tcl_CmdProc	TeststaticpkgCmd;

static Tcl_CmdProc	TesttranslatefilenameCmd;

static Tcl_CmdProc	TestupvarCmd;

static Tcl_ObjCmdProc	TestWrongNumArgsObjCmd;


static Tcl_ObjCmdProc	TestGetIndexFromObjStructObjCmd;


static Tcl_CmdProc	TestChannelCmd;

static Tcl_CmdProc	TestChannelEventCmd;

static Tcl_ObjCmdProc	TestFilesystemObjCmd;


static Tcl_ObjCmdProc	TestSimpleFilesystemObjCmd;


static void		TestReport(const char *cmd, Tcl_Obj *arg1,
			    Tcl_Obj *arg2);
static Tcl_Obj *	TestReportGetNativePath(Tcl_Obj *pathPtr);
static Tcl_FSStatProc TestReportStat;
static Tcl_FSAccessProc TestReportAccess;
static Tcl_FSOpenFileChannelProc TestReportOpenFileChannel;


static Tcl_FSMatchInDirectoryProc TestReportMatchInDirectory;


static Tcl_FSChdirProc TestReportChdir;
static Tcl_FSLstatProc TestReportLstat;
static Tcl_FSCopyFileProc TestReportCopyFile;
static Tcl_FSDeleteFileProc TestReportDeleteFile;
static Tcl_FSRenameFileProc TestReportRenameFile;
static Tcl_FSCreateDirectoryProc TestReportCreateDirectory;
static Tcl_FSCopyDirectoryProc TestReportCopyDirectory;

static Tcl_FSRemoveDirectoryProc TestReportRemoveDirectory;





static int TestReportLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
	Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr);
static Tcl_FSLinkProc TestReportLink;
static Tcl_FSFileAttrStringsProc TestReportFileAttrStrings;

static Tcl_FSFileAttrsGetProc TestReportFileAttrsGet;

static Tcl_FSFileAttrsSetProc TestReportFileAttrsSet;

static Tcl_FSUtimeProc TestReportUtime;

static Tcl_FSNormalizePathProc TestReportNormalizePath;

static Tcl_FSPathInFilesystemProc TestReportInFilesystem;
static Tcl_FSFreeInternalRepProc TestReportFreeInternalRep;
static Tcl_FSDupInternalRepProc TestReportDupInternalRep;

static Tcl_FSStatProc SimpleStat;
static Tcl_FSAccessProc SimpleAccess;
static Tcl_FSOpenFileChannelProc SimpleOpenFileChannel;

static Tcl_FSListVolumesProc SimpleListVolumes;
static Tcl_FSPathInFilesystemProc SimplePathInFilesystem;

static Tcl_Obj *	SimpleRedirect(Tcl_Obj *pathPtr);
static Tcl_FSMatchInDirectoryProc SimpleMatchInDirectory;
static Tcl_ObjCmdProc	TestUtfNextCmd;
static Tcl_ObjCmdProc	TestUtfPrevCmd;

static Tcl_ObjCmdProc	TestNumUtfCharsCmd;
static Tcl_ObjCmdProc	TestFindFirstCmd;
static Tcl_ObjCmdProc	TestFindLastCmd;
static Tcl_ObjCmdProc	TestHashSystemHashCmd;


#if defined(HAVE_CPUID) || defined(_WIN32)
static Tcl_ObjCmdProc	TestcpuidCmd;


#endif

static Tcl_Filesystem testReportingFilesystem = {
    "reporting",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    TestReportInFilesystem, /* path in */
    TestReportDupInternalRep,
    TestReportFreeInternalRep,
    NULL, /* native to norm */
    NULL, /* convert to native */
    TestReportNormalizePath,
    NULL, /* path type */
    NULL, /* separator */
    TestReportStat,
    TestReportAccess,
    TestReportOpenFileChannel,
    TestReportMatchInDirectory,
    TestReportUtime,
    TestReportLink,
    NULL /* list volumes */,
    TestReportFileAttrStrings,
    TestReportFileAttrsGet,
    TestReportFileAttrsSet,
    TestReportCreateDirectory,
    TestReportRemoveDirectory,
    TestReportDeleteFile,
    TestReportCopyFile,
    TestReportRenameFile,
    TestReportCopyDirectory,
    TestReportLstat,
    (Tcl_FSLoadFileProc *) TestReportLoadFile,
    NULL /* cwd */,
    TestReportChdir
};

static Tcl_Filesystem simpleFilesystem = {
    "simple",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    SimplePathInFilesystem,
    NULL,
    NULL,
    /* No internal to normalized, since we don't create any
     * pure 'internal' Tcl_Obj path representations */
    NULL,
    /* No create native rep function, since we don't use it
     * or 'Tcl_FSNewNativePath' */
    NULL,
    /* Normalize path isn't needed - we assume paths only have
     * one representation */
    NULL,
    NULL,
    NULL,
    SimpleStat,
    SimpleAccess,
    SimpleOpenFileChannel,
    SimpleMatchInDirectory,
    NULL,
    /* We choose not to support symbolic links inside our vfs's */
    NULL,
    SimpleListVolumes,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    /* No copy file - fallback will occur at Tcl level */







|
|
<
|
>
|
>
|
>
|
>
|
>
|
>
|
>
|
>
|
>
>
|
>
|
>
>
|
>
>
|
>
>
|
>
>



|
>
|
>
|
>
>
|
>
|
>
>
|
>
>
|
>
|
>
|
>
|
>
|
>
|
>
|
>
|
>
>
|
>
|
>
|
>
>






|
>
|
>
|
>
|
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|

|
>
>

|
>
|
>
|
>
|
>
|
>
>
|
|
|
>
|
>
|
>
|
>
>
|
>
>
|
>
|
>
|
>
>
|
>
>



|
|
|
>
>
|
>
>
|
|
|
|
|
|
|
>
|
>
>
>
>
>
|
<
<
|
>
|
>
|
>
|
>
|
>
|
|
|

|
|
|
>
|
|
>

|
|
|
>
|
|
|
|
>
>
|
|
>
>






|
|
|


|


|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|






|













|
|
|
|



|







230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409


410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
			    Tcl_Interp *interp, const char *fileName,
			    const char *modeString, int permissions);
static int		PretendTclpStat(const char *path, struct stat *buf);
static int		TestStatProc1(const char *path, struct stat *buf);
static int		TestStatProc2(const char *path, struct stat *buf);
static int		TestStatProc3(const char *path, struct stat *buf);
#endif
static int		TestasyncCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);

static int		TestcmdinfoCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestcmdtokenCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestcmdtraceCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestconcatobjCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestcreatecommandCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestdcallCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestdelCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestdelassocdataCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestdoubledigitsObjCmd(ClientData dummy,
					       Tcl_Interp* interp,
					       int objc, Tcl_Obj* const objv[]);
static int		TestdstringCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestencodingObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestevalexObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestevalobjvObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TesteventObjCmd(ClientData unused,
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *const objv[]);
static int		TesteventProc(Tcl_Event *event, int flags);
static int		TesteventDeleteProc(Tcl_Event *event,
			    ClientData clientData);
static int		TestexithandlerCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestexprlongCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestexprlongobjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestexprdoubleCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestexprdoubleobjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestexprparserObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestexprstringCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestfileCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int		TestfilelinkCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int		TestfeventCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestgetassocdataCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestgetintCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestgetplatformCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestgetvarfullnameCmd(
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		TestinterpdeleteCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestlinkCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestlocaleCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestMathFunc(ClientData clientData,
			    Tcl_Interp *interp, Tcl_Value *args,
			    Tcl_Value *resultPtr);
static int		TestMathFunc2(ClientData clientData,
			    Tcl_Interp *interp, Tcl_Value *args,
			    Tcl_Value *resultPtr);
static int		TestmainthreadCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestsetmainloopCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestexitmainloopCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestpanicCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestparserObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestparsevarObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestparsevarnameObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestregexpObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestreturnObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		TestregexpXflags(char *string,
			    int length, int *cflagsPtr, int *eflagsPtr);
static int		TestsaveresultCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		TestsaveresultFree(char *blockPtr);
static int		TestsetassocdataCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestsetCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		Testset2Cmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestseterrorcodeCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestsetobjerrorcodeCmd(
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		TestsetplatformCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TeststaticpkgCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TesttranslatefilenameCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestupvarCmd(ClientData dummy,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestWrongNumArgsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		TestGetIndexFromObjStructObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		TestChannelCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestChannelEventCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc, const char **argv);
static int		TestFilesystemObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestSimpleFilesystemObjCmd(
			    ClientData dummy, Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		TestReport(const char *cmd, Tcl_Obj *arg1,
			    Tcl_Obj *arg2);
static Tcl_Obj *	TestReportGetNativePath(Tcl_Obj *pathPtr);
static int		TestReportStat(Tcl_Obj *path, Tcl_StatBuf *buf);
static int		TestReportAccess(Tcl_Obj *path, int mode);
static Tcl_Channel	TestReportOpenFileChannel(
			    Tcl_Interp *interp, Tcl_Obj *fileName,
			    int mode, int permissions);
static int		TestReportMatchInDirectory(Tcl_Interp *interp,
			    Tcl_Obj *resultPtr, Tcl_Obj *dirPtr,
			    const char *pattern, Tcl_GlobTypeData *types);
static int		TestReportChdir(Tcl_Obj *dirName);
static int		TestReportLstat(Tcl_Obj *path, Tcl_StatBuf *buf);
static int		TestReportCopyFile(Tcl_Obj *src, Tcl_Obj *dst);
static int		TestReportDeleteFile(Tcl_Obj *path);
static int		TestReportRenameFile(Tcl_Obj *src, Tcl_Obj *dst);
static int		TestReportCreateDirectory(Tcl_Obj *path);
static int		TestReportCopyDirectory(Tcl_Obj *src,
			    Tcl_Obj *dst, Tcl_Obj **errorPtr);
static int		TestReportRemoveDirectory(Tcl_Obj *path,
			    int recursive, Tcl_Obj **errorPtr);
static int		TestReportLoadFile(Tcl_Interp *interp,
			    Tcl_Obj *fileName, Tcl_LoadHandle *handlePtr,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
static Tcl_Obj *	TestReportLink(Tcl_Obj *path,
			    Tcl_Obj *to, int linkType);


static const char **	TestReportFileAttrStrings(
			    Tcl_Obj *fileName, Tcl_Obj **objPtrRef);
static int		TestReportFileAttrsGet(Tcl_Interp *interp,
			    int index, Tcl_Obj *fileName, Tcl_Obj **objPtrRef);
static int		TestReportFileAttrsSet(Tcl_Interp *interp,
			    int index, Tcl_Obj *fileName, Tcl_Obj *objPtr);
static int		TestReportUtime(Tcl_Obj *fileName,
			    struct utimbuf *tval);
static int		TestReportNormalizePath(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, int nextCheckpoint);
static int		TestReportInFilesystem(Tcl_Obj *pathPtr, ClientData *clientDataPtr);
static void		TestReportFreeInternalRep(ClientData clientData);
static ClientData	TestReportDupInternalRep(ClientData clientData);

static int		SimpleStat(Tcl_Obj *path, Tcl_StatBuf *buf);
static int		SimpleAccess(Tcl_Obj *path, int mode);
static Tcl_Channel	SimpleOpenFileChannel(Tcl_Interp *interp,
			    Tcl_Obj *fileName, int mode, int permissions);
static Tcl_Obj *	SimpleListVolumes(void);
static int		SimplePathInFilesystem(
			    Tcl_Obj *pathPtr, ClientData *clientDataPtr);
static Tcl_Obj *	SimpleRedirect(Tcl_Obj *pathPtr);
static int		SimpleMatchInDirectory(
			    Tcl_Interp *interp, Tcl_Obj *resultPtr,
			    Tcl_Obj *dirPtr, const char *pattern,
			    Tcl_GlobTypeData *types);
static int		TestNumUtfCharsCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		TestHashSystemHashCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
#if defined(HAVE_CPUID) || defined(__WIN32__)
static int		TestcpuidCmd (ClientData dummy,
			    Tcl_Interp* interp, int objc,
			    Tcl_Obj *CONST objv[]);
#endif

static Tcl_Filesystem testReportingFilesystem = {
    "reporting",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    &TestReportInFilesystem, /* path in */
    &TestReportDupInternalRep,
    &TestReportFreeInternalRep,
    NULL, /* native to norm */
    NULL, /* convert to native */
    &TestReportNormalizePath,
    NULL, /* path type */
    NULL, /* separator */
    &TestReportStat,
    &TestReportAccess,
    &TestReportOpenFileChannel,
    &TestReportMatchInDirectory,
    &TestReportUtime,
    &TestReportLink,
    NULL /* list volumes */,
    &TestReportFileAttrStrings,
    &TestReportFileAttrsGet,
    &TestReportFileAttrsSet,
    &TestReportCreateDirectory,
    &TestReportRemoveDirectory,
    &TestReportDeleteFile,
    &TestReportCopyFile,
    &TestReportRenameFile,
    &TestReportCopyDirectory,
    &TestReportLstat,
    (Tcl_FSLoadFileProc *) &TestReportLoadFile,
    NULL /* cwd */,
    &TestReportChdir
};

static Tcl_Filesystem simpleFilesystem = {
    "simple",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    &SimplePathInFilesystem,
    NULL,
    NULL,
    /* No internal to normalized, since we don't create any
     * pure 'internal' Tcl_Obj path representations */
    NULL,
    /* No create native rep function, since we don't use it
     * or 'Tcl_FSNewNativePath' */
    NULL,
    /* Normalize path isn't needed - we assume paths only have
     * one representation */
    NULL,
    NULL,
    NULL,
    &SimpleStat,
    &SimpleAccess,
    &SimpleOpenFileChannel,
    &SimpleMatchInDirectory,
    NULL,
    /* We choose not to support symbolic links inside our vfs's */
    NULL,
    &SimpleListVolumes,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    /* No copy file - fallback will occur at Tcl level */
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

int
Tcltest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_ValueType t3ArgTypes[2];


    Tcl_Obj **objv, *objPtr;
    int objc, index;
    static const char *const specialOptions[] = {
	"-appinitprocerror", "-appinitprocdeleteinterp",
	"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
    };

    /* TIP #268: Full patchlevel instead of just major.minor */

    if (Tcl_PkgProvide(interp, "Tcltest", TCL_PATCH_LEVEL) == TCL_ERROR) {
	return TCL_ERROR;
    }

    /*
     * Create additional commands and math functions for testing Tcl.
     */

    Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "noop", NoopCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "teststringbytes", TeststringbytesObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
	    TestGetIndexFromObjStructObjCmd, NULL, NULL);
#ifdef USE_OBSOLETE_FS_HOOKS
    Tcl_CreateCommand(interp, "testaccessproc", TestaccessprocCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testopenfilechannelproc",
    	    TestopenfilechannelprocCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, NULL,
	    NULL);
#endif
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testdel", TestdelCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsObjCmd,
			 NULL, NULL);
    Tcl_DStringInit(&dstring);
    Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testevent", TesteventObjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprlongobj", TestexprlongobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprdouble", TestexprdoubleCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprdoubleobj", TestexprdoubleobjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testhashsystemhash",
	    TestHashSystemHashCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testgetint", TestgetintCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
	    TestgetvarfullnameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testlink", TestlinkCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
	    (ClientData) TCL_LEAVE_ERR_MSG, NULL);
    Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
	    (ClientData) TCL_LEAVE_ERR_MSG, NULL);
    Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
	    TestsetobjerrorcodeCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testutfnext",
	    TestUtfNextCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testutfprev",
	    TestUtfPrevCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testnumutfchars",
	    TestNumUtfCharsCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindfirst",
	    TestFindFirstCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindlast",
	    TestFindLastCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsize", TestsizeCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testtranslatefilename",
	    TesttranslatefilenameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
    Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123);
    Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345);
    Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
	    NULL, NULL);
#if defined(HAVE_CPUID) || defined(_WIN32)
    Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
	    NULL, NULL);
#endif
    t3ArgTypes[0] = TCL_EITHER;
    t3ArgTypes[1] = TCL_EITHER;
    Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
	    NULL);

#ifdef TCL_THREADS
    if (TclThread_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }
#endif

    /*
     * Check for special options used in ../tests/main.test
     */

    objPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
    if (objPtr != NULL) {
	if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL,
		TCL_EXACT, &index) == TCL_OK)) {
	    switch (index) {
	    case 0:
		return TCL_ERROR;







>
|

|














|
|
|
<
<

|

|

|

|

|


|
|


|

|

|
|

|


|

|

|
|
|

|



|

|


|

|

|

|

|

|

|

|

|

|
|


|

|

|

|

|

|

|

|
|
|

|

|

|

|

|

|

|

|

|





|

|
<
<
<
<

|
<
<
<
<

|
<

|

|
|


|


|

|
|

|




|











|
|
|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584


585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692




693
694




695
696

697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

int
Tcltest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_ValueType t3ArgTypes[2];

    Tcl_Obj *listPtr;
    Tcl_Obj **objv;
    int objc, index;
    static const char *specialOptions[] = {
	"-appinitprocerror", "-appinitprocdeleteinterp",
	"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
    };

    /* TIP #268: Full patchlevel instead of just major.minor */

    if (Tcl_PkgProvide(interp, "Tcltest", TCL_PATCH_LEVEL) == TCL_ERROR) {
	return TCL_ERROR;
    }

    /*
     * Create additional commands and math functions for testing Tcl.
     */

    Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "noop", NoopCmd, (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, (ClientData) 0, NULL);


    Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
	    TestGetIndexFromObjStructObjCmd, (ClientData) 0, NULL);
#ifdef USE_OBSOLETE_FS_HOOKS
    Tcl_CreateCommand(interp, "testaccessproc", TestaccessprocCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateCommand(interp, "testopenfilechannelproc",
    	    TestopenfilechannelprocCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, (ClientData) 0,
	    NULL);
#endif
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testdel", TestdelCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsObjCmd,
			 NULL, NULL);
    Tcl_DStringInit(&dstring);
    Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testevent", TesteventObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testexprlongobj", TestexprlongobjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testexprdouble", TestexprdoubleCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testexprdoubleobj", TestexprdoubleobjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testhashsystemhash",
	    TestHashSystemHashCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetint", TestgetintCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
	    TestgetvarfullnameCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testlink", TestlinkCmd, (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
	    (ClientData) TCL_LEAVE_ERR_MSG, NULL);
    Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
	    (ClientData) TCL_LEAVE_ERR_MSG, NULL);
    Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
	    TestsetobjerrorcodeCmd, (ClientData) 0, NULL);




    Tcl_CreateObjCommand(interp, "testnumutfchars",
	    TestNumUtfCharsCmd, (ClientData) 0, NULL);




    Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
	    (ClientData) 0, NULL);

    Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
	    (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testtranslatefilename",
	    TesttranslatefilenameCmd, (ClientData) 0, NULL);
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, (ClientData) 0, NULL);
    Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123);
    Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345);
    Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, (ClientData) 0,
	    NULL);
    Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
	    (ClientData) NULL, NULL);
    Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
	    (ClientData) NULL, NULL);
#if defined(HAVE_CPUID) || defined(__WIN32__)
    Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
	    (ClientData) 0, NULL);
#endif
    t3ArgTypes[0] = TCL_EITHER;
    t3ArgTypes[1] = TCL_EITHER;
    Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
	    (ClientData) 0);

#ifdef TCL_THREADS
    if (TclThread_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }
#endif

    /*
     * Check for special options used in ../tests/main.test
     */

    listPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
    if (listPtr != NULL) {
	if (Tcl_ListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL,
		TCL_EXACT, &index) == TCL_OK)) {
	    switch (index) {
	    case 0:
		return TCL_ERROR;
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
 *
 * Side effects:
 *	Creates, deletes, and invokes handlers.
 *
 *----------------------------------------------------------------------
 */


static int
TestasyncCmd(
    ClientData dummy,			/* Not used. */
    Tcl_Interp *interp,			/* Current interpreter. */
    int argc,				/* Number of arguments. */
    const char **argv)			/* Argument strings. */
{
    TestAsyncHandler *asyncPtr, *prevPtr;
    int id, code;
    static int nextId = 1;
    (void)dummy;

    if (argc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	asyncPtr = (TestAsyncHandler *)ckalloc(sizeof(TestAsyncHandler));
	asyncPtr->command = (char *)ckalloc(strlen(argv[2]) + 1);
	strcpy(asyncPtr->command, argv[2]);
        Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
                                            INT2PTR(asyncPtr->id));
	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
        Tcl_MutexUnlock(&asyncTestMutex);

	Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id));
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 2) {
            Tcl_MutexLock(&asyncTestMutex);
	    while (firstHandler != NULL) {
		asyncPtr = firstHandler;
		firstHandler = asyncPtr->nextPtr;
		Tcl_AsyncDelete(asyncPtr->handler);
		ckfree(asyncPtr->command);
		ckfree((char *)asyncPtr);
	    }
            Tcl_MutexUnlock(&asyncTestMutex);
	    return TCL_OK;
	}
	if (argc != 3) {
	    goto wrongNumArgs;
	}







>










|



|






|
|









>
|








|







775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
 *
 * Side effects:
 *	Creates, deletes, and invokes handlers.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestasyncCmd(
    ClientData dummy,			/* Not used. */
    Tcl_Interp *interp,			/* Current interpreter. */
    int argc,				/* Number of arguments. */
    const char **argv)			/* Argument strings. */
{
    TestAsyncHandler *asyncPtr, *prevPtr;
    int id, code;
    static int nextId = 1;
    char buf[TCL_INTEGER_SPACE];

    if (argc < 2) {
	wrongNumArgs:
	Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	asyncPtr = (TestAsyncHandler *) ckalloc(sizeof(TestAsyncHandler));
	asyncPtr->command = ckalloc(strlen(argv[2]) + 1);
	strcpy(asyncPtr->command, argv[2]);
        Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
                                            INT2PTR(asyncPtr->id));
	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
        Tcl_MutexUnlock(&asyncTestMutex);
	TclFormatInt(buf, asyncPtr->id);
	Tcl_SetResult(interp, buf, TCL_VOLATILE);
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 2) {
            Tcl_MutexLock(&asyncTestMutex);
	    while (firstHandler != NULL) {
		asyncPtr = firstHandler;
		firstHandler = asyncPtr->nextPtr;
		Tcl_AsyncDelete(asyncPtr->handler);
		ckfree(asyncPtr->command);
		ckfree((char *) asyncPtr);
	    }
            Tcl_MutexUnlock(&asyncTestMutex);
	    return TCL_OK;
	}
	if (argc != 3) {
	    goto wrongNumArgs;
	}
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
	    if (prevPtr == NULL) {
		firstHandler = asyncPtr->nextPtr;
	    } else {
		prevPtr->nextPtr = asyncPtr->nextPtr;
	    }
	    Tcl_AsyncDelete(asyncPtr->handler);
	    ckfree(asyncPtr->command);
	    ckfree((char *)asyncPtr);
	    break;
	}
        Tcl_MutexUnlock(&asyncTestMutex);
    } else if (strcmp(argv[1], "mark") == 0) {
	if (argc != 5) {
	    goto wrongNumArgs;
	}
	if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) {
	    return TCL_ERROR;
	}
	Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_AsyncMark(asyncPtr->handler);
		break;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(argv[3], -1));
	Tcl_MutexUnlock(&asyncTestMutex);

	return code;
#ifdef TCL_THREADS
    } else if (strcmp(argv[1], "marklater") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_ThreadId threadID;
		if (Tcl_CreateThread(&threadID, AsyncThreadProc,
			INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
			TCL_THREAD_NOFLAGS) != TCL_OK) {
		    Tcl_AppendResult(interp, "can't create thread", NULL);
		    Tcl_MutexUnlock(&asyncTestMutex);
		    return TCL_ERROR;
		}
		break;
	    }
	}
        Tcl_MutexUnlock(&asyncTestMutex);







|











|







<
|
>















|

|







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
	    if (prevPtr == NULL) {
		firstHandler = asyncPtr->nextPtr;
	    } else {
		prevPtr->nextPtr = asyncPtr->nextPtr;
	    }
	    Tcl_AsyncDelete(asyncPtr->handler);
	    ckfree(asyncPtr->command);
	    ckfree((char *) asyncPtr);
	    break;
	}
        Tcl_MutexUnlock(&asyncTestMutex);
    } else if (strcmp(argv[1], "mark") == 0) {
	if (argc != 5) {
	    goto wrongNumArgs;
	}
	if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) {
	    return TCL_ERROR;
	}
        Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_AsyncMark(asyncPtr->handler);
		break;
	    }
	}

        Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetResult(interp, (char *)argv[3], TCL_VOLATILE);
	return code;
#ifdef TCL_THREADS
    } else if (strcmp(argv[1], "marklater") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_ThreadId threadID;
		if (Tcl_CreateThread(&threadID, AsyncThreadProc,
			(ClientData) INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
			TCL_THREAD_NOFLAGS) != TCL_OK) {
		    Tcl_SetResult(interp, "can't create thread", TCL_STATIC);
		    Tcl_MutexUnlock(&asyncTestMutex);
		    return TCL_ERROR;
		}
		break;
	    }
	}
        Tcl_MutexUnlock(&asyncTestMutex);
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);
    const char *listArgv[4], *cmd;
    char string[TCL_INTEGER_SPACE];

    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
            asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) {
            break;
        }
    }
    Tcl_MutexUnlock(&asyncTestMutex);

    if (!asyncPtr) {
        /* Woops - this one was deleted between the AsyncMark and now */
        return TCL_OK;
    }







|
|
<
<







918
919
920
921
922
923
924
925
926


927
928
929
930
931
932
933
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);
    const char *listArgv[4], *cmd;
    char string[TCL_INTEGER_SPACE];

    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) break;


    }
    Tcl_MutexUnlock(&asyncTestMutex);

    if (!asyncPtr) {
        /* Woops - this one was deleted between the AsyncMark and now */
        return TCL_OK;
    }
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */


static int
TestcmdinfoCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_CmdInfo info;
    (void)dummy;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option cmdName\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original",
		CmdDelProc1);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DStringInit(&delString);
	Tcl_DeleteCommand(interp, argv[2]);
	Tcl_DStringResult(interp, &delString);
    } else if (strcmp(argv[1], "get") == 0) {
	if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
	    Tcl_AppendResult(interp, "??", NULL);
	    return TCL_OK;
	}
	if (info.proc == CmdProc1) {
	    Tcl_AppendResult(interp, "CmdProc1", " ",
		    (char *) info.clientData, NULL);
	} else if (info.proc == CmdProc2) {
	    Tcl_AppendResult(interp, "CmdProc2", " ",







|








<















|







1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestcmdinfoCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_CmdInfo info;


    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option cmdName\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original",
		CmdDelProc1);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DStringInit(&delString);
	Tcl_DeleteCommand(interp, argv[2]);
	Tcl_DStringResult(interp, &delString);
    } else if (strcmp(argv[1], "get") == 0) {
	if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
	    Tcl_SetResult(interp, "??", TCL_STATIC);
	    return TCL_OK;
	}
	if (info.proc == CmdProc1) {
	    Tcl_AppendResult(interp, "CmdProc1", " ",
		    (char *) info.clientData, NULL);
	} else if (info.proc == CmdProc2) {
	    Tcl_AppendResult(interp, "CmdProc2", " ",
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982

983
984
985
986
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
	} else {
	    Tcl_AppendResult(interp, " stringProc", NULL);
	}
    } else if (strcmp(argv[1], "modify") == 0) {
	info.proc = CmdProc2;
	info.clientData = (ClientData) "new_command_data";
	info.objProc = NULL;
	info.objClientData = NULL;
	info.deleteProc = CmdDelProc2;
	info.deleteData = (ClientData) "new_delete_data";
	if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
	}
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, get, or modify", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}


static int
CmdProc1(
    ClientData clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL);
    return TCL_OK;
}


static int
CmdProc2(
    ClientData clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|



|

|









>











>







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
	} else {
	    Tcl_AppendResult(interp, " stringProc", NULL);
	}
    } else if (strcmp(argv[1], "modify") == 0) {
	info.proc = CmdProc2;
	info.clientData = (ClientData) "new_command_data";
	info.objProc = NULL;
	info.objClientData = (ClientData) NULL;
	info.deleteProc = CmdDelProc2;
	info.deleteData = (ClientData) "new_delete_data";
	if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
	    Tcl_SetResult(interp, "0", TCL_STATIC);
	} else {
	    Tcl_SetResult(interp, "1", TCL_STATIC);
	}
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, get, or modify", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

	/*ARGSUSED*/
static int
CmdProc1(
    ClientData clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL);
    return TCL_OK;
}

	/*ARGSUSED*/
static int
CmdProc2(
    ClientData clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */


static int
TestcmdtokenCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|







1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestcmdtokenCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
 * Side effects:
 *	Creates and deletes a command trace, and tests the invocation of
 *	a procedure by the command trace.
 *
 *----------------------------------------------------------------------
 */


static int
TestcmdtraceCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    int result;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option script\"", NULL);
	return TCL_ERROR;
    }

    if (strcmp(argv[1], "tracetest") == 0) {
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, 50000,
		(Tcl_CmdTraceProc *) CmdTraceProc, &buffer);
	result = Tcl_Eval(interp, argv[2]);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[1], "deletetest") == 0) {
	/*
	 * Create a command trace then eval a script to check whether it is
	 * called. Note that this trace procedure removes itself as a further
	 * check of the robustness of the trace proc calling code in
	 * TclExecuteByteCode.
	 */

	cmdTrace = Tcl_CreateTrace(interp, 50000,
		(Tcl_CmdTraceProc *) CmdTraceDeleteProc, NULL);
	Tcl_Eval(interp, argv[2]);
    } else if (strcmp(argv[1], "leveltest") == 0) {
	Interp *iPtr = (Interp *) interp;
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4,
		(Tcl_CmdTraceProc *) CmdTraceProc, &buffer);
	result = Tcl_Eval(interp, argv[2]);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);







|



















|
















|





|







1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
 * Side effects:
 *	Creates and deletes a command trace, and tests the invocation of
 *	a procedure by the command trace.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestcmdtraceCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    int result;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option script\"", NULL);
	return TCL_ERROR;
    }

    if (strcmp(argv[1], "tracetest") == 0) {
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, 50000,
		(Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer);
	result = Tcl_Eval(interp, argv[2]);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[1], "deletetest") == 0) {
	/*
	 * Create a command trace then eval a script to check whether it is
	 * called. Note that this trace procedure removes itself as a further
	 * check of the robustness of the trace proc calling code in
	 * TclExecuteByteCode.
	 */

	cmdTrace = Tcl_CreateTrace(interp, 50000,
		(Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL);
	Tcl_Eval(interp, argv[2]);
    } else if (strcmp(argv[1], "leveltest") == 0) {
	Interp *iPtr = (Interp *) interp;
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4,
		(Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer);
	result = Tcl_Eval(interp, argv[2]);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
		CreatedCommandProc, NULL, NULL);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
    } else if (strcmp(argv[1], "create2") == 0) {
	Tcl_CreateCommand(interp, "value:at:",
		CreatedCommandProc2, NULL, NULL);
    } else if (strcmp(argv[1], "delete2") == 0) {
	Tcl_DeleteCommand(interp, "value:at:");
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, create2, or delete2", NULL);
	return TCL_ERROR;
    }







|




|







1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
		CreatedCommandProc, (ClientData) NULL, NULL);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
    } else if (strcmp(argv[1], "create2") == 0) {
	Tcl_CreateCommand(interp, "value:at:",
		CreatedCommandProc2, (ClientData) NULL, NULL);
    } else if (strcmp(argv[1], "delete2") == 0) {
	Tcl_DeleteCommand(interp, "value:at:");
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, create2, or delete2", NULL);
	return TCL_ERROR;
    }
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
 *
 * Side effects:
 *	Creates and deletes interpreters.
 *
 *----------------------------------------------------------------------
 */


static int
TestdcallCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|







1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
 *
 * Side effects:
 *	Creates and deletes interpreters.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestdcallCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
 *
 * Side effects:
 *	Creates a command.
 *
 *----------------------------------------------------------------------
 */


static int
TestdelCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr;
    Tcl_Interp *slave;

    if (argc != 4) {
	Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
	return TCL_ERROR;
    }

    slave = Tcl_GetSlave(interp, argv[1]);
    if (slave == NULL) {
	return TCL_ERROR;
    }

    dPtr = (DelCmd *)ckalloc(sizeof(DelCmd));
    dPtr->interp = interp;
    dPtr->deleteCmd = (char *)ckalloc(strlen(argv[3]) + 1);
    strcpy(dPtr->deleteCmd, argv[3]);

    Tcl_CreateCommand(slave, argv[2], DelCmdProc, (ClientData) dPtr,
	    DelDeleteProc);
    return TCL_OK;
}

static int
DelCmdProc(
    ClientData clientData,	/* String result to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr = (DelCmd *) clientData;

    Tcl_AppendResult(interp, dPtr->deleteCmd, NULL);
    ckfree(dPtr->deleteCmd);
    ckfree((char *)dPtr);
    return TCL_OK;
}

static void
DelDeleteProc(
    ClientData clientData)	/* String command to evaluate. */
{
    DelCmd *dPtr = (DelCmd *)clientData;

    Tcl_Eval(dPtr->interp, dPtr->deleteCmd);
    Tcl_ResetResult(dPtr->interp);
    ckfree(dPtr->deleteCmd);
    ckfree((char *)dPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestdelassocdataCmd --
 *







|




















|

|


















|







|




|







1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
 *
 * Side effects:
 *	Creates a command.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestdelCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr;
    Tcl_Interp *slave;

    if (argc != 4) {
	Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
	return TCL_ERROR;
    }

    slave = Tcl_GetSlave(interp, argv[1]);
    if (slave == NULL) {
	return TCL_ERROR;
    }

    dPtr = (DelCmd *) ckalloc(sizeof(DelCmd));
    dPtr->interp = interp;
    dPtr->deleteCmd = (char *) ckalloc((unsigned) (strlen(argv[3]) + 1));
    strcpy(dPtr->deleteCmd, argv[3]);

    Tcl_CreateCommand(slave, argv[2], DelCmdProc, (ClientData) dPtr,
	    DelDeleteProc);
    return TCL_OK;
}

static int
DelCmdProc(
    ClientData clientData,	/* String result to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr = (DelCmd *) clientData;

    Tcl_AppendResult(interp, dPtr->deleteCmd, NULL);
    ckfree(dPtr->deleteCmd);
    ckfree((char *) dPtr);
    return TCL_OK;
}

static void
DelDeleteProc(
    ClientData clientData)	/* String command to evaluate. */
{
    DelCmd *dPtr = (DelCmd *) clientData;

    Tcl_Eval(dPtr->interp, dPtr->deleteCmd);
    Tcl_ResetResult(dPtr->interp);
    ckfree(dPtr->deleteCmd);
    ckfree((char *) dPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestdelassocdataCmd --
 *
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
 *
 * Side effects:
 *	Creates, deletes, and invokes handlers.
 *
 *----------------------------------------------------------------------
 */


static int
TestdstringCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|







1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
 *
 * Side effects:
 *	Creates, deletes, and invokes handlers.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestdstringCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720


1721
1722
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735

1736
1737
1738
1739
1740
1741
1742
	    goto wrongNumArgs;
	}
	if (strcmp(argv[2], "staticsmall") == 0) {
	    Tcl_SetResult(interp, "short", TCL_STATIC);
	} else if (strcmp(argv[2], "staticlarge") == 0) {
	    Tcl_SetResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", TCL_STATIC);
	} else if (strcmp(argv[2], "free") == 0) {
	    char *s = ckalloc(100);
	    strcpy(s, "This is a malloc-ed string");
	    Tcl_SetResult(interp, s, TCL_DYNAMIC);
	} else if (strcmp(argv[2], "special") == 0) {
	    char *s = (char*)ckalloc(100) + 16;


	    strcpy(s, "This is a specially-allocated string");
	    Tcl_SetResult(interp, s, SpecialFree);
	} else {
	    Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
		    "\": must be staticsmall, staticlarge, free, or special",
		    NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringGetResult(interp, &dstring);
    } else if (strcmp(argv[1], "length") == 0) {


	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_DStringLength(&dstring)));

    } else if (strcmp(argv[1], "result") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringResult(interp, &dstring);
    } else if (strcmp(argv[1], "trunc") == 0) {
	if (argc != 3) {







|
|
<

|
>
>
|
<








>




|
>







1810
1811
1812
1813
1814
1815
1816
1817
1818

1819
1820
1821
1822
1823

1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
	    goto wrongNumArgs;
	}
	if (strcmp(argv[2], "staticsmall") == 0) {
	    Tcl_SetResult(interp, "short", TCL_STATIC);
	} else if (strcmp(argv[2], "staticlarge") == 0) {
	    Tcl_SetResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", TCL_STATIC);
	} else if (strcmp(argv[2], "free") == 0) {
	    Tcl_SetResult(interp, (char *) ckalloc(100), TCL_DYNAMIC);
	    strcpy(interp->result, "This is a malloc-ed string");

	} else if (strcmp(argv[2], "special") == 0) {
	    interp->result = (char *) ckalloc(100);
	    interp->result += 4;
	    interp->freeProc = SpecialFree;
	    strcpy(interp->result, "This is a specially-allocated string");

	} else {
	    Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
		    "\": must be staticsmall, staticlarge, free, or special",
		    NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringGetResult(interp, &dstring);
    } else if (strcmp(argv[1], "length") == 0) {
	char buf[TCL_INTEGER_SPACE];

	if (argc != 2) {
	    goto wrongNumArgs;
	}
	TclFormatInt(buf, Tcl_DStringLength(&dstring));
	Tcl_SetResult(interp, buf, TCL_VOLATILE);
    } else if (strcmp(argv[1], "result") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringResult(interp, &dstring);
    } else if (strcmp(argv[1], "trunc") == 0) {
	if (argc != 3) {
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
 * The procedure below is used as a special freeProc to test how well
 * Tcl_DStringGetResult handles freeProc's other than free.
 */

static void SpecialFree(blockPtr)
    char *blockPtr;			/* Block to free. */
{
    ckfree(blockPtr - 16);
}

/*
 *----------------------------------------------------------------------
 *
 * TestencodingCmd --
 *
 *	This procedure implements the "testencoding" command.  It is used
 *	to test the encoding package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Load encodings.
 *
 *----------------------------------------------------------------------
 */


static int
TestencodingObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Encoding encoding;
    int index, length;
    const char *string;
    TclEncoding *encodingPtr;
    static const char *optionStrings[] = {
	"create",	"delete",	NULL
    };
    enum options {
	ENC_CREATE,	ENC_DELETE
    };

    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case ENC_CREATE: {
	Tcl_EncodingType type;

	if (objc != 5) {
	    return TCL_ERROR;
	}
	encodingPtr = (TclEncoding *)ckalloc(sizeof(TclEncoding));
	encodingPtr->interp = interp;

	string = Tcl_GetStringFromObj(objv[3], &length);
	encodingPtr->toUtfCmd = (char *)ckalloc(length + 1);
	memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1);

	string = Tcl_GetStringFromObj(objv[4], &length);
	encodingPtr->fromUtfCmd = (char *)ckalloc(length + 1);
	memcpy(encodingPtr->fromUtfCmd, string, (unsigned) (length + 1));

	string = Tcl_GetStringFromObj(objv[2], &length);

	type.encodingName = string;
	type.toUtfProc = EncodingToUtfProc;
	type.fromUtfProc = EncodingFromUtfProc;







|



















|









|




















|



|



|







1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
 * The procedure below is used as a special freeProc to test how well
 * Tcl_DStringGetResult handles freeProc's other than free.
 */

static void SpecialFree(blockPtr)
    char *blockPtr;			/* Block to free. */
{
    ckfree(blockPtr - 4);
}

/*
 *----------------------------------------------------------------------
 *
 * TestencodingCmd --
 *
 *	This procedure implements the "testencoding" command.  It is used
 *	to test the encoding package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Load encodings.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestencodingObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Encoding encoding;
    int index, length;
    char *string;
    TclEncoding *encodingPtr;
    static const char *optionStrings[] = {
	"create",	"delete",	NULL
    };
    enum options {
	ENC_CREATE,	ENC_DELETE
    };

    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case ENC_CREATE: {
	Tcl_EncodingType type;

	if (objc != 5) {
	    return TCL_ERROR;
	}
	encodingPtr = (TclEncoding *) ckalloc(sizeof(TclEncoding));
	encodingPtr->interp = interp;

	string = Tcl_GetStringFromObj(objv[3], &length);
	encodingPtr->toUtfCmd = (char *) ckalloc((unsigned) (length + 1));
	memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1);

	string = Tcl_GetStringFromObj(objv[4], &length);
	encodingPtr->fromUtfCmd = (char *) ckalloc((unsigned) (length + 1));
	memcpy(encodingPtr->fromUtfCmd, string, (unsigned) (length + 1));

	string = Tcl_GetStringFromObj(objv[2], &length);

	type.encodingName = string;
	type.toUtfProc = EncodingToUtfProc;
	type.fromUtfProc = EncodingFromUtfProc;
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
    return TCL_OK;
}

static void
EncodingFreeProc(
    ClientData clientData)	/* ClientData associated with type. */
{
    TclEncoding *encodingPtr = (TclEncoding *)clientData;


    ckfree((char *)encodingPtr->toUtfCmd);
    ckfree((char *)encodingPtr->fromUtfCmd);
    ckfree((char *)encodingPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestevalexObjCmd --
 *







|

>
|
|
|







2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
    return TCL_OK;
}

static void
EncodingFreeProc(
    ClientData clientData)	/* ClientData associated with type. */
{
    TclEncoding *encodingPtr;

    encodingPtr = (TclEncoding *) clientData;
    ckfree((char *) encodingPtr->toUtfCmd);
    ckfree((char *) encodingPtr->fromUtfCmd);
    ckfree((char *) encodingPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestevalexObjCmd --
 *
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
TestevalexObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int length, flags;
    const char *script;

    flags = 0;
    if (objc == 3) {
	const char *global = Tcl_GetString(objv[2]);
	if (strcmp(global, "global") != 0) {
	    Tcl_AppendResult(interp, "bad value \"", global,
		    "\": must be global", NULL);
	    return TCL_ERROR;
	}
	flags = TCL_EVAL_GLOBAL;
    } else if (objc != 2) {







|



|







2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
TestevalexObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int length, flags;
    char *script;

    flags = 0;
    if (objc == 3) {
	char *global = Tcl_GetStringFromObj(objv[2], &length);
	if (strcmp(global, "global") != 0) {
	    Tcl_AppendResult(interp, "bad value \"", global,
		    "\": must be global", NULL);
	    return TCL_ERROR;
	}
	flags = TCL_EVAL_GLOBAL;
    } else if (objc != 2) {
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
	TCL_QUEUE_HEAD,
	TCL_QUEUE_TAIL,
	TCL_QUEUE_MARK
    };
    TestEvent *ev;		/* Event to be queued */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "subcommand",
	    TCL_EXACT, &subCmdIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (subCmdIndex) {
    case 0:			/* queue */
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name position script");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], positions,
		"position specifier", TCL_EXACT, &posIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	ev = (TestEvent *)ckalloc(sizeof(TestEvent));
	ev->header.proc = TesteventProc;
	ev->header.nextPtr = NULL;
	ev->interp = interp;
	ev->command = objv[4];
	Tcl_IncrRefCount(ev->command);
	ev->tag = objv[2];
	Tcl_IncrRefCount(ev->tag);







|
















|







2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
	TCL_QUEUE_HEAD,
	TCL_QUEUE_TAIL,
	TCL_QUEUE_MARK
    };
    TestEvent *ev;		/* Event to be queued */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "subcommand",
	    TCL_EXACT, &subCmdIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (subCmdIndex) {
    case 0:			/* queue */
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name position script");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], positions,
		"position specifier", TCL_EXACT, &posIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	ev = (TestEvent *) ckalloc(sizeof(TestEvent));
	ev->header.proc = TesteventProc;
	ev->header.nextPtr = NULL;
	ev->interp = interp;
	ev->command = objv[4];
	Tcl_IncrRefCount(ev->command);
	ev->tag = objv[2];
	Tcl_IncrRefCount(ev->tag);
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
static int
TesteventDeleteProc(
    Tcl_Event *event,		/* Event to examine */
    ClientData clientData)	/* Tcl_Obj containing the name of the event(s)
				 * to remove */
{
    TestEvent *ev;		/* Event to examine */
    const char *evNameStr;
    Tcl_Obj *targetName;	/* Name of the event(s) to delete */
    const char *targetNameStr;

    if (event->proc != TesteventProc) {
	return 0;
    }
    targetName = (Tcl_Obj *) clientData;
    targetNameStr = (char *) Tcl_GetString(targetName);
    ev = (TestEvent *) event;
    evNameStr = Tcl_GetString(ev->tag);
    if (strcmp(evNameStr, targetNameStr) == 0) {
	Tcl_DecrRefCount(ev->tag);
	Tcl_DecrRefCount(ev->command);
	return 1;
    } else {
	return 0;
    }







|

|





|

|







2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
static int
TesteventDeleteProc(
    Tcl_Event *event,		/* Event to examine */
    ClientData clientData)	/* Tcl_Obj containing the name of the event(s)
				 * to remove */
{
    TestEvent *ev;		/* Event to examine */
    char *evNameStr;
    Tcl_Obj *targetName;	/* Name of the event(s) to delete */
    char *targetNameStr;

    if (event->proc != TesteventProc) {
	return 0;
    }
    targetName = (Tcl_Obj *) clientData;
    targetNameStr = (char *) Tcl_GetStringFromObj(targetName, NULL);
    ev = (TestEvent *) event;
    evNameStr = Tcl_GetStringFromObj(ev->tag, NULL);
    if (strcmp(evNameStr, targetNameStr) == 0) {
	Tcl_DecrRefCount(ev->tag);
	Tcl_DecrRefCount(ev->command);
	return 1;
    } else {
	return 0;
    }
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
}

static void
ExitProcOdd(
    ClientData clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    int len;

    sprintf(buf, "odd %d\n", (int)PTR2INT(clientData));
    len = strlen(buf);
    if (len != (int) write(1, buf, len)) {
	Tcl_Panic("ExitProcOdd: unable to write to stdout");
    }
}

static void
ExitProcEven(
    ClientData clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    int len;

    sprintf(buf, "even %d\n", (int)PTR2INT(clientData));
    len = strlen(buf);
    if (len != (int) write(1, buf, len)) {
	Tcl_Panic("ExitProcEven: unable to write to stdout");
    }
}

/*
 *----------------------------------------------------------------------
 *







|

|

|









|

|

|







2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
}

static void
ExitProcOdd(
    ClientData clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    size_t len;

    sprintf(buf, "odd %d\n", PTR2INT(clientData));
    len = strlen(buf);
    if (len != (size_t) write(1, buf, len)) {
	Tcl_Panic("ExitProcOdd: unable to write to stdout");
    }
}

static void
ExitProcEven(
    ClientData clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    size_t len;

    sprintf(buf, "even %d\n", PTR2INT(clientData));
    len = strlen(buf);
    if (len != (size_t) write(1, buf, len)) {
	Tcl_Panic("ExitProcEven: unable to write to stdout");
    }
}

/*
 *----------------------------------------------------------------------
 *
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
 *
 * Side effects:
 *	Deletes one or more interpreters.
 *
 *----------------------------------------------------------------------
 */


static int
TestinterpdeleteCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|







2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
 *
 * Side effects:
 *	Deletes one or more interpreters.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestinterpdeleteCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
 * Side effects:
 *	Creates and deletes various variable links, plus returns
 *	values of the linked variables.
 *
 *----------------------------------------------------------------------
 */


static int
TestlinkCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    static int intVar = 43;
    static int boolVar = 4;
    static double realVar = 1.23;
    static Tcl_WideInt wideVar = Tcl_LongAsWide(79);
    static char *stringVar = NULL;
    static char charVar = '@';
    static unsigned char ucharVar = 130;
    static short shortVar = 3000;
    static unsigned short ushortVar = 60000;
    static unsigned int uintVar = 0xBEEFFEED;
    static long longVar = 123456789L;
    static unsigned long ulongVar = 3456789012UL;
    static float floatVar = 4.5;
    static Tcl_WideUInt uwideVar = (Tcl_WideUInt) Tcl_LongAsWide(123);
    static int created = 0;
    char buffer[2*TCL_DOUBLE_SPACE];
    int writable, flag;







|
















|







2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
 * Side effects:
 *	Creates and deletes various variable links, plus returns
 *	values of the linked variables.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestlinkCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    static int intVar = 43;
    static int boolVar = 4;
    static double realVar = 1.23;
    static Tcl_WideInt wideVar = Tcl_LongAsWide(79);
    static char *stringVar = NULL;
    static char charVar = '@';
    static unsigned char ucharVar = 130;
    static short shortVar = 3000;
    static unsigned short ushortVar = 60000;
    static unsigned int uintVar = 0xbeeffeed;
    static long longVar = 123456789L;
    static unsigned long ulongVar = 3456789012UL;
    static float floatVar = 4.5;
    static Tcl_WideUInt uwideVar = (Tcl_WideUInt) Tcl_LongAsWide(123);
    static int created = 0;
    char buffer[2*TCL_DOUBLE_SPACE];
    int writable, flag;
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
	if (argv[5][0] != 0) {
	    if (stringVar != NULL) {
		ckfree(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *)ckalloc(strlen(argv[5]) + 1);
		strcpy(stringVar, argv[5]);
	    }
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {
		Tcl_DecrRefCount(tmp);







|







3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
	if (argv[5][0] != 0) {
	    if (stringVar != NULL) {
		ckfree(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *) ckalloc((unsigned) (strlen(argv[5]) + 1));
		strcpy(stringVar, argv[5]);
	    }
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {
		Tcl_DecrRefCount(tmp);
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
	if (argv[5][0] != 0) {
	    if (stringVar != NULL) {
		ckfree(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *)ckalloc(strlen(argv[5]) + 1);
		strcpy(stringVar, argv[5]);
	    }
	    Tcl_UpdateLinkedVar(interp, "string");
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {







|







3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
	if (argv[5][0] != 0) {
	    if (stringVar != NULL) {
		ckfree(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *) ckalloc((unsigned) (strlen(argv[5]) + 1));
		strcpy(stringVar, argv[5]);
	    }
	    Tcl_UpdateLinkedVar(interp, "string");
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
TestlocaleCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int index;
    const char *locale;

    static const char *optionStrings[] = {
	"ctype", "numeric", "time", "collate", "monetary",
	"all",	NULL
    };
    static const int lcTypes[] = {
	LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY,
	LC_ALL
    };

    /*
     * LC_CTYPE, etc. correspond to the indices for the strings.
     */







|


|


|







3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
TestlocaleCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int index;
    char *locale;

    static const char *optionStrings[] = {
    	"ctype", "numeric", "time", "collate", "monetary",
	"all",	NULL
    };
    static CONST int lcTypes[] = {
	LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY,
	LC_ALL
    };

    /*
     * LC_CTYPE, etc. correspond to the indices for the strings.
     */
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestMathFunc(
    ClientData clientData,	/* Integer value to return. */
    Tcl_Interp *interp,		/* Not used. */
    Tcl_Value *args,		/* Not used. */
    Tcl_Value *resultPtr)	/* Where to store result. */
{







|







3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestMathFunc(
    ClientData clientData,	/* Integer value to return. */
    Tcl_Interp *interp,		/* Not used. */
    Tcl_Value *args,		/* Not used. */
    Tcl_Value *resultPtr)	/* Where to store result. */
{
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestMathFunc2(
    ClientData clientData,	/* Integer value to return. */
    Tcl_Interp *interp,		/* Used to report errors. */
    Tcl_Value *args,		/* Points to an array of two Tcl_Value structs
				 * for the two arguments. */
    Tcl_Value *resultPtr)	/* Where to store the result. */







|







3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestMathFunc2(
    ClientData clientData,	/* Integer value to return. */
    Tcl_Interp *interp,		/* Used to report errors. */
    Tcl_Value *args,		/* Points to an array of two Tcl_Value structs
				 * for the two arguments. */
    Tcl_Value *resultPtr)	/* Where to store the result. */
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
 *	None.
 *
 * Side effects:
 *	Releases storage.
 *
 *----------------------------------------------------------------------
 */

static void
CleanupTestSetassocdataTests(
    ClientData clientData,	/* Data to be released. */
    Tcl_Interp *interp)		/* Interpreter being deleted. */
{
    ckfree((char *)clientData);
}

/*
 *----------------------------------------------------------------------
 *
 * TestparserObjCmd --
 *







|





|







3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
 *	None.
 *
 * Side effects:
 *	Releases storage.
 *
 *----------------------------------------------------------------------
 */
	/* ARGSUSED */
static void
CleanupTestSetassocdataTests(
    ClientData clientData,	/* Data to be released. */
    Tcl_Interp *interp)		/* Interpreter being deleted. */
{
    ckfree((char *) clientData);
}

/*
 *----------------------------------------------------------------------
 *
 * TestparserObjCmd --
 *
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
static int
TestparserObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length");
	return TCL_ERROR;
    }







|







3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
static int
TestparserObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    char *script;
    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length");
	return TCL_ERROR;
    }
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
static int
TestexprparserObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "expr length");
	return TCL_ERROR;
    }







|







3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
static int
TestexprparserObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    char *script;
    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "expr length");
	return TCL_ERROR;
    }
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
static int
TestparsevarnameObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    int append, length, dummy;
    Tcl_Parse parse;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length append");
	return TCL_ERROR;
    }







|







3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
static int
TestparsevarnameObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    char *script;
    int append, length, dummy;
    Tcl_Parse parse;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length append");
	return TCL_ERROR;
    }
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */


static int
TestregexpObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, ii, indices, stringLength, match, about;
    int hasxflags, cflags, eflags;
    Tcl_RegExp regExpr;
    const char *string;
    Tcl_Obj *objPtr;
    Tcl_RegExpInfo info;
    static const char *options[] = {
	"-indices",	"-nocase",	"-about",	"-expanded",
	"-line",	"-linestop",	"-lineanchor",
	"-xflags",
	"--",		NULL







|










|







3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestregexpObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, ii, indices, stringLength, match, about;
    int hasxflags, cflags, eflags;
    Tcl_RegExp regExpr;
    char *string;
    Tcl_Obj *objPtr;
    Tcl_RegExpInfo info;
    static const char *options[] = {
	"-indices",	"-nocase",	"-about",	"-expanded",
	"-line",	"-linestop",	"-lineanchor",
	"-xflags",
	"--",		NULL
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
    indices = 0;
    about = 0;
    cflags = REG_ADVANCED;
    eflags = 0;
    hasxflags = 0;

    for (i = 1; i < objc; i++) {
	const char *name;
	int index;

	name = Tcl_GetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,







|







3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
    indices = 0;
    about = 0;
    cflags = REG_ADVANCED;
    eflags = 0;
    hasxflags = 0;

    for (i = 1; i < objc; i++) {
	char *name;
	int index;

	name = Tcl_GetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if (objc - i < hasxflags + 2 - about) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
	return TCL_ERROR;
    }
    objc -= i;
    objv += i;

    if (hasxflags) {
	string = Tcl_GetStringFromObj(objv[0], &stringLength);







|







3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if (objc - i < hasxflags + 2 - about) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
	return TCL_ERROR;
    }
    objc -= i;
    objv += i;

    if (hasxflags) {
	string = Tcl_GetStringFromObj(objv[0], &stringLength);
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
	/*
	 * Set the interpreter's object result to an integer object w/
	 * value 0.
	 */

	Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
	if (objc > 2 && (cflags&REG_EXPECT) && indices) {
	    const char *varName;
	    const char *value;
	    int start, end;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    varName = Tcl_GetString(objv[2]);
	    TclRegExpRangeUniChar(regExpr, -1, &start, &end);
	    sprintf(resinfo, "%d %d", start, end-1);
	    value = Tcl_SetVar(interp, varName, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", NULL);
		return TCL_ERROR;
	    }
	} else if (cflags & TCL_REG_CANMATCH) {
	    const char *varName;
	    const char *value;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    Tcl_RegExpGetInfo(regExpr, &info);
	    varName = Tcl_GetString(objv[2]);
	    sprintf(resinfo, "%ld", info.extendStart);
	    value = Tcl_SetVar(interp, varName, resinfo, 0);







|














|







3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
	/*
	 * Set the interpreter's object result to an integer object w/
	 * value 0.
	 */

	Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
	if (objc > 2 && (cflags&REG_EXPECT) && indices) {
	    char *varName;
	    const char *value;
	    int start, end;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    varName = Tcl_GetString(objv[2]);
	    TclRegExpRangeUniChar(regExpr, -1, &start, &end);
	    sprintf(resinfo, "%d %d", start, end-1);
	    value = Tcl_SetVar(interp, varName, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", NULL);
		return TCL_ERROR;
	    }
	} else if (cflags & TCL_REG_CANMATCH) {
	    char *varName;
	    const char *value;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    Tcl_RegExpGetInfo(regExpr, &info);
	    varName = Tcl_GetString(objv[2]);
	    sprintf(resinfo, "%ld", info.extendStart);
	    value = Tcl_SetVar(interp, varName, resinfo, 0);
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
 *	regexec flags word, as appropriate.
 *
 *----------------------------------------------------------------------
 */

static void
TestregexpXflags(
    const char *string,	/* The string of flags. */
    int length,			/* The length of the string in bytes. */
    int *cflagsPtr,		/* compile flags word */
    int *eflagsPtr)		/* exec flags word */
{
    int i, cflags, eflags;

    cflags = *cflagsPtr;







|







4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
 *	regexec flags word, as appropriate.
 *
 *----------------------------------------------------------------------
 */

static void
TestregexpXflags(
    char *string,		/* The string of flags. */
    int length,			/* The length of the string in bytes. */
    int *cflagsPtr,		/* compile flags word */
    int *eflagsPtr)		/* exec flags word */
{
    int i, cflags, eflags;

    cflags = *cflagsPtr;
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */


static int
TestreturnObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{







|







4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestreturnObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key data_item\"", NULL);
	return TCL_ERROR;
    }

    buf = ckalloc(strlen(argv[2]) + 1);
    strcpy(buf, argv[2]);

    /*
     * If we previously associated a malloced value with the variable,
     * free it before associating a new value.
     */








|







4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key data_item\"", NULL);
	return TCL_ERROR;
    }

    buf = ckalloc((unsigned) strlen(argv[2]) + 1);
    strcpy(buf, argv[2]);

    /*
     * If we previously associated a malloced value with the variable,
     * free it before associating a new value.
     */

4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
    } else {
	Tcl_AppendResult(interp, "unsupported platform: should be one of "
		"unix, or windows", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static int
TestsizeCmd(
    ClientData clientData,      /* Unused */
    Tcl_Interp* interp,         /* Tcl interpreter */
    int objc,                   /* Parameter count */
    Tcl_Obj *const * objv)      /* Parameter vector */
{
    if (objc != 2) {
        goto syntax;
    }
    if (strcmp(Tcl_GetString(objv[1]), "time_t") == 0) {
        Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(time_t)));
        return TCL_OK;
    }
    if (strcmp(Tcl_GetString(objv[1]), "st_mtime") == 0) {
        Tcl_StatBuf *statPtr;
        Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(statPtr->st_mtime)));
        return TCL_OK;
    }
    if (strcmp(Tcl_GetString(objv[1]), "unichar") == 0) {
        Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(Tcl_UniChar)));
        return TCL_OK;
    }

syntax:
    Tcl_WrongNumArgs(interp, 1, objv, "time_t|st_mtime|unichar");
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststaticpkgCmd --
 *
 *	This procedure implements the "teststaticpkg" command.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







4223
4224
4225
4226
4227
4228
4229





























4230
4231
4232
4233
4234
4235
4236
    } else {
	Tcl_AppendResult(interp, "unsupported platform: should be one of "
		"unix, or windows", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}






























/*
 *----------------------------------------------------------------------
 *
 * TeststaticpkgCmd --
 *
 *	This procedure implements the "teststaticpkg" command.
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
}

/*
 *----------------------------------------------------------------------
 *
 * TestupvarCmd --
 *
 *	This procedure implements the "testupvar" command.  It is used
 *	to test Tcl_UpVar and Tcl_UpVar2.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Creates or modifies an "upvar" reference.
 *
 *----------------------------------------------------------------------
 */


static int
TestupvarCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|











|







4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
}

/*
 *----------------------------------------------------------------------
 *
 * TestupvarCmd --
 *
 *	This procedure implements the "testupvar2" command.  It is used
 *	to test Tcl_UpVar and Tcl_UpVar2.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Creates or modifies an "upvar" reference.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestupvarCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestseterrorcodeCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc > 6) {
	Tcl_SetResult(interp, "too many args", TCL_STATIC);
	return TCL_ERROR;
    }
    switch (argc) {
    case 1:
	Tcl_SetErrorCode(interp, "NONE", NULL);
	break;
    case 2:
	Tcl_SetErrorCode(interp, argv[1], NULL);
	break;
    case 3:
	Tcl_SetErrorCode(interp, argv[1], argv[2], NULL);
	break;
    case 4:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], NULL);
	break;
    case 5:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], NULL);
	break;
    case 6:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
		argv[5], NULL);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetobjerrorcodeCmd --







|











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<







4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405

















4406
4407

4408
4409
4410
4411
4412
4413
4414
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestseterrorcodeCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc > 6) {
	Tcl_SetResult(interp, "too many args", TCL_STATIC);
	return TCL_ERROR;
    }

















    Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
	    argv[5], NULL);

    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetobjerrorcodeCmd --
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestsetobjerrorcodeCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{







|







4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestsetobjerrorcodeCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
 *
 * Side effects:
 *	Creates and deletes interpreters.
 *
 *----------------------------------------------------------------------
 */


static int
TestfeventCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    static Tcl_Interp *interp2 = NULL;
    int code;
    Tcl_Channel chan;

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg ...?", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "cmd") == 0) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cmd script", NULL);
	    return TCL_ERROR;







|













|







4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
 *
 * Side effects:
 *	Creates and deletes interpreters.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestfeventCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    static Tcl_Interp *interp2 = NULL;
    int code;
    Tcl_Channel chan;

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg arg ...?", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "cmd") == 0) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cmd script", NULL);
	    return TCL_ERROR;
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
static int
TestpanicCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    char *argString;

    /*
     *  Put the arguments into a var args structure
     *  Append all of the arguments together separated by spaces
     */

    argString = Tcl_Merge(argc-1, argv+1);
    Tcl_Panic("%s", argString);
    ckfree(argString);

    return TCL_OK;
}

static int
TestfileCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    Tcl_Obj *const argv[])	/* The argument objects. */
{
    int force, i, j, result;
    Tcl_Obj *error = NULL;
    const char *subcmd;

    if (argc < 3) {
	return TCL_ERROR;
    }

    force = 0;
    i = 2;







|








|



|









|







4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
static int
TestpanicCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    const char *argString;

    /*
     *  Put the arguments into a var args structure
     *  Append all of the arguments together separated by spaces
     */

    argString = Tcl_Merge(argc-1, argv+1);
    Tcl_Panic("%s", argString);
    ckfree((char *)argString);

    return TCL_OK;
}

static int
TestfileCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    Tcl_Obj *const argv[])	/* The argument objects. */
{
    int force, i, j, result;
    Tcl_Obj *error = NULL;
    char *subcmd;

    if (argc < 3) {
	return TCL_ERROR;
    }

    force = 0;
    i = 2;
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
static int
TestgetvarfullnameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *name, *arg;
    int flags = 0;
    Tcl_Namespace *namespacePtr;
    Tcl_CallFrame *framePtr;
    Tcl_Var variable;
    int result;

    if (objc != 3) {







|







4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
static int
TestgetvarfullnameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    char *name, *arg;
    int flags = 0;
    Tcl_Namespace *namespacePtr;
    Tcl_CallFrame *framePtr;
    Tcl_Var variable;
    int result;

    if (objc != 3) {
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
    Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetTimesObjCmd --
 *
 *	This procedure implements the "gettimes" command.  It is used for
 *	computing the time needed for various basic operations such as reading
 *	variables, allocating memory, sprintf, converting variables, etc.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Allocates and frees memory, sets a variable "a" in the interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
GetTimesObjCmd(
    ClientData unused,		/* Unused. */
    Tcl_Interp *interp,		/* The current interpreter. */
    int objc,			/* Number of arguments. (not used)*/
    Tcl_Obj *const dummy[])	/* The argument objects (not used). */
{
    Interp *iPtr = (Interp *) interp;
    int i, n;
    double timePer;
    Tcl_Time start, stop;
    Tcl_Obj *objPtr, **objv;
    const char *s;
    char newString[TCL_INTEGER_SPACE];
    (void)objc;
    (void)dummy;

    /* alloc & free 100000 times */
    fprintf(stderr, "alloc & free 100000 6 word items\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	objPtr = (Tcl_Obj *)ckalloc(sizeof(Tcl_Obj));
	ckfree((char *)objPtr);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per alloc+free\n", timePer/100000);

    /* alloc 5000 times */
    fprintf(stderr, "alloc 5000 6 word items\n");
    objv = (Tcl_Obj **) ckalloc(5000 * sizeof(Tcl_Obj *));
    Tcl_GetTime(&start);
    for (i = 0;  i < 5000;  i++) {
	objv[i] = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj));
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per alloc\n", timePer/5000);

    /* free 5000 times */
    fprintf(stderr, "free 5000 6 word items\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 5000;  i++) {
	ckfree((char *)objv[i]);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per free\n", timePer/5000);

    /* Tcl_NewObj 5000 times */
    fprintf(stderr, "Tcl_NewObj 5000 times\n");







|















|


|
|








<
<





|
|




















|







4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725


4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
    Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetTimesCmd --
 *
 *	This procedure implements the "gettimes" command.  It is used for
 *	computing the time needed for various basic operations such as reading
 *	variables, allocating memory, sprintf, converting variables, etc.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Allocates and frees memory, sets a variable "a" in the interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
GetTimesCmd(
    ClientData unused,		/* Unused. */
    Tcl_Interp *interp,		/* The current interpreter. */
    int argc,			/* The number of arguments. */
    const char **argv)		/* The argument strings. */
{
    Interp *iPtr = (Interp *) interp;
    int i, n;
    double timePer;
    Tcl_Time start, stop;
    Tcl_Obj *objPtr, **objv;
    const char *s;
    char newString[TCL_INTEGER_SPACE];



    /* alloc & free 100000 times */
    fprintf(stderr, "alloc & free 100000 6 word items\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	objPtr = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj));
	ckfree((char *) objPtr);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per alloc+free\n", timePer/100000);

    /* alloc 5000 times */
    fprintf(stderr, "alloc 5000 6 word items\n");
    objv = (Tcl_Obj **) ckalloc(5000 * sizeof(Tcl_Obj *));
    Tcl_GetTime(&start);
    for (i = 0;  i < 5000;  i++) {
	objv[i] = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj));
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per alloc\n", timePer/5000);

    /* free 5000 times */
    fprintf(stderr, "free 5000 6 word items\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 5000;  i++) {
	ckfree((char *) objv[i]);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per free\n", timePer/5000);

    /* Tcl_NewObj 5000 times */
    fprintf(stderr, "Tcl_NewObj 5000 times\n");
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
    for (i = 0;  i < 5000;  i++) {
	objPtr = objv[i];
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per Tcl_DecrRefCount\n", timePer/5000);
    ckfree((char *)objv);

    /* TclGetString 100000 times */
    fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n");
    objPtr = Tcl_NewStringObj("12345", -1);
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	(void) TclGetString(objPtr);







|







4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
    for (i = 0;  i < 5000;  i++) {
	objPtr = objv[i];
	Tcl_DecrRefCount(objPtr);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per Tcl_DecrRefCount\n", timePer/5000);
    ckfree((char *) objv);

    /* TclGetString 100000 times */
    fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n");
    objPtr = Tcl_NewStringObj("12345", -1);
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	(void) TclGetString(objPtr);
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962

4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
{
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststringbytesObjCmd --
 *	Returns bytearray value of the bytes in argument string rep
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TeststringbytesObjCmd(
    ClientData dummy,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int n;
    const unsigned char *p;
    (void)dummy;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    p = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(p, n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbytestringObjCmd --
 *
 *	This object-based procedure constructs a string which can
 *	possibly contain invalid UTF-8 bytes.
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestbytestringObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int n = 0;
    const char *p;
    (void)dummy;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "bytearray");
	return TCL_ERROR;
    }

    p = (const char *)Tcl_GetByteArrayFromObj(objv[1], &n);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetCmd --
 *
 *	Implements the "testset{err,noerr}" cmds that are used when testing
 *	Tcl_Set/GetVar C Api with/without TCL_LEAVE_ERR_MSG flag
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *     Variables may be set.
 *
 *----------------------------------------------------------------------
 */


static int
TestsetCmd(
    ClientData data,		/* Additional flags for Get/SetVar2. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 2) {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














>



|







4924
4925
4926
4927
4928
4929
4930









































































4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
{
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *









































































 * TestsetCmd --
 *
 *	Implements the "testset{err,noerr}" cmds that are used when testing
 *	Tcl_Set/GetVar C Api with/without TCL_LEAVE_ERR_MSG flag
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *     Variables may be set.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestsetCmd(
    ClientData data,		/* Additional flags for Get/SetVar2. */
    register Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 2) {
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
		argv[0], " varName ?newValue?\"", NULL);
	return TCL_ERROR;
    }
}
static int
Testset2Cmd(
    ClientData data,		/* Additional flags for Get/SetVar2. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 3) {







|







4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
		argv[0], " varName ?newValue?\"", NULL);
	return TCL_ERROR;
    }
}
static int
Testset2Cmd(
    ClientData data,		/* Additional flags for Get/SetVar2. */
    register Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 3) {
5038
5039
5040
5041
5042
5043
5044

5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestsaveresultCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    Interp* iPtr = (Interp*) interp;
    int discard, result, index;
    Tcl_SavedResult state;
    Tcl_Obj *objPtr;
    static const char *optionStrings[] = {
	"append", "dynamic", "free", "object", "small", NULL
    };
    enum options {







>



|



<







5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035

5036
5037
5038
5039
5040
5041
5042
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestsaveresultCmd(
    ClientData dummy,		/* Not used. */
    register Tcl_Interp *interp,/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{

    int discard, result, index;
    Tcl_SavedResult state;
    Tcl_Obj *objPtr;
    static const char *optionStrings[] = {
	"append", "dynamic", "free", "object", "small", NULL
    };
    enum options {
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
	char *buf = ckalloc(200);

	strcpy(buf, "free result");
	Tcl_SetResult(interp, buf, TCL_DYNAMIC);
	break;
    }
    case RESULT_DYNAMIC:
	Tcl_SetResult(interp, (char *)"dynamic result", TestsaveresultFree);
	break;
    case RESULT_OBJECT:
	objPtr = Tcl_NewStringObj("object result", -1);
	Tcl_SetObjResult(interp, objPtr);
	break;
    }








|







5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
	char *buf = ckalloc(200);

	strcpy(buf, "free result");
	Tcl_SetResult(interp, buf, TCL_DYNAMIC);
	break;
    }
    case RESULT_DYNAMIC:
	Tcl_SetResult(interp, "dynamic result", TestsaveresultFree);
	break;
    case RESULT_OBJECT:
	objPtr = Tcl_NewStringObj("object result", -1);
	Tcl_SetObjResult(interp, objPtr);
	break;
    }

5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
    } else {
	Tcl_RestoreResult(interp, &state);
	result = TCL_OK;
    }

    switch ((enum options) index) {
    case RESULT_DYNAMIC: {
	int present = iPtr->freeProc == TestsaveresultFree;
	int called = freeCount;

	Tcl_AppendElement(interp, called ? "called" : "notCalled");
	Tcl_AppendElement(interp, present ? "present" : "missing");
	break;
    }
    case RESULT_OBJECT:







|







5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
    } else {
	Tcl_RestoreResult(interp, &state);
	result = TCL_OK;
    }

    switch ((enum options) index) {
    case RESULT_DYNAMIC: {
	int present = interp->freeProc == TestsaveresultFree;
	int called = freeCount;

	Tcl_AppendElement(interp, called ? "called" : "notCalled");
	Tcl_AppendElement(interp, present ? "present" : "missing");
	break;
    }
    case RESULT_OBJECT:
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
 *----------------------------------------------------------------------
 *
 * MainLoop --
 *
 *	A main loop set by TestsetmainloopCmd below.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Event handlers could do anything.
 *
 *----------------------------------------------------------------------
 */








|







5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
 *----------------------------------------------------------------------
 *
 * MainLoop --
 *
 *	A main loop set by TestsetmainloopCmd below.
 *
 * Results:
 * 	None.
 *
 * Side effects:
 *	Event handlers could do anything.
 *
 *----------------------------------------------------------------------
 */

5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
 *
 *----------------------------------------------------------------------
 */

static int
TestsetmainloopCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
  exitMainLoop = 0;
  Tcl_SetMainLoop(MainLoop);
  return TCL_OK;
}







|







5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
 *
 *----------------------------------------------------------------------
 */

static int
TestsetmainloopCmd(
    ClientData dummy,		/* Not used. */
    register Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
  exitMainLoop = 0;
  Tcl_SetMainLoop(MainLoop);
  return TCL_OK;
}
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
 *
 *----------------------------------------------------------------------
 */

static int
TestexitmainloopCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
  exitMainLoop = 1;
  return TCL_OK;
}
#ifdef USE_OBSOLETE_FS_HOOKS







|







5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
 *
 *----------------------------------------------------------------------
 */

static int
TestexitmainloopCmd(
    ClientData dummy,		/* Not used. */
    register Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
  exitMainLoop = 1;
  return TCL_OK;
}
#ifdef USE_OBSOLETE_FS_HOOKS
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TestChannelCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Interpreter for result. */
    int argc,			/* Count of additional args. */
    const char **argv)		/* Additional arg strings. */
{







|







5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestChannelCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Interpreter for result. */
    int argc,			/* Count of additional args. */
    const char **argv)		/* Additional arg strings. */
{
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854

5855
5856
5857
5858
5859
5860
5861
		 curPtr != NULL;
		 nextPtrPtr = &(curPtr->nextPtr), curPtr = curPtr->nextPtr) {

		if (strcmp(argv[2], Tcl_GetChannelName(curPtr->chan)) == 0) {
		    *nextPtrPtr = curPtr->nextPtr;
		    curPtr->nextPtr = NULL;
		    chan = curPtr->chan;
		    ckfree((char *)curPtr);
		    break;
		}
	    }
	} else {
	    chan = Tcl_GetChannel(interp, argv[2], &mode);
	}
	if (chan == (Tcl_Channel) NULL) {
	    return TCL_ERROR;
	}
	chanPtr		= (Channel *) chan;
	statePtr	= chanPtr->state;
	chanPtr		= statePtr->topChanPtr;
	chan		= (Tcl_Channel) chanPtr;
    } else {

	statePtr	= NULL;
	chan		= NULL;
    }

    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);







|














>







5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
		 curPtr != NULL;
		 nextPtrPtr = &(curPtr->nextPtr), curPtr = curPtr->nextPtr) {

		if (strcmp(argv[2], Tcl_GetChannelName(curPtr->chan)) == 0) {
		    *nextPtrPtr = curPtr->nextPtr;
		    curPtr->nextPtr = NULL;
		    chan = curPtr->chan;
		    ckfree((char *) curPtr);
		    break;
		}
	    }
	} else {
	    chan = Tcl_GetChannel(interp, argv[2], &mode);
	}
	if (chan == (Tcl_Channel) NULL) {
	    return TCL_ERROR;
	}
	chanPtr		= (Channel *) chan;
	statePtr	= chanPtr->state;
	chanPtr		= statePtr->topChanPtr;
	chan		= (Tcl_Channel) chanPtr;
    } else {
	/* lint */
	statePtr	= NULL;
	chan		= NULL;
    }

    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
	Tcl_RegisterChannel(NULL, chan); /* prevent closing */
	Tcl_UnregisterChannel(interp, chan);

	Tcl_CutChannel(chan);

	/* Remember the channel in the pool of detached channels */

	det = (TestChannel *)ckalloc(sizeof(TestChannel));
	det->chan     = chan;
	det->nextPtr  = firstDetached;
	firstDetached = det;

	return TCL_OK;
    }








|







5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
	Tcl_RegisterChannel(NULL, chan); /* prevent closing */
	Tcl_UnregisterChannel(interp, chan);

	Tcl_CutChannel(chan);

	/* Remember the channel in the pool of detached channels */

	det = (TestChannel *) ckalloc(sizeof(TestChannel));
	det->chan     = chan;
	det->nextPtr  = firstDetached;
	firstDetached = det;

	return TCL_OK;
    }

6072
6073
6074
6075
6076
6077
6078
6079
6080

6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan)));

	return TCL_OK;
    }

    if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, statePtr->channelName, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) {
	hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
	if (hTblPtr == NULL) {
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') &&
	    (strncmp(cmdName, "outputbuffered", len) == 0)) {
	if (argc != 3) {







<
|
>




















|







6056
6057
6058
6059
6060
6061
6062

6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}


	TclFormatInt(buf, (long)(size_t)Tcl_GetChannelThread(chan));
	Tcl_AppendResult(interp, buf, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, statePtr->channelName, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) {
	hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
	if (hTblPtr == NULL) {
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') &&
	    (strncmp(cmdName, "outputbuffered", len) == 0)) {
	if (argc != 3) {
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr  = (Channel *) Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_READABLE) {
		Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
	if (argc != 3) {







|







6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr  = (Channel *) Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_READABLE) {
		Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
	if (argc != 3) {
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_WRITABLE) {
		Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
	/*







|







6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_WRITABLE) {
		Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
	/*
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
 *
 * Side effects:
 *	Creates, deletes and returns channel event handlers.
 *
 *----------------------------------------------------------------------
 */


static int
TestChannelEventCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







|







6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
 *
 * Side effects:
 *	Creates, deletes and returns channel event handlers.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestChannelEventCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
		Tcl_Panic("TestChannelEventCmd: damaged event script list");
	    }
	    prevEsPtr->nextPtr = esPtr->nextPtr;
	}
	Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		TclChannelEventScriptInvoker, (ClientData) esPtr);
	Tcl_DecrRefCount(esPtr->scriptPtr);
	ckfree((char *)esPtr);

	return TCL_OK;
    }

    if ((cmd[0] == 'l') && (strncmp(cmd, "list", (unsigned) len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],







|







6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
		Tcl_Panic("TestChannelEventCmd: damaged event script list");
	    }
	    prevEsPtr->nextPtr = esPtr->nextPtr;
	}
	Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		TclChannelEventScriptInvoker, (ClientData) esPtr);
	Tcl_DecrRefCount(esPtr->scriptPtr);
	ckfree((char *) esPtr);

	return TCL_OK;
    }

    if ((cmd[0] == 'l') && (strncmp(cmd, "list", (unsigned) len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = nextEsPtr) {
	    nextEsPtr = esPtr->nextPtr;
	    Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		    TclChannelEventScriptInvoker, (ClientData) esPtr);
	    Tcl_DecrRefCount(esPtr->scriptPtr);
	    ckfree((char *)esPtr);
	}
	statePtr->scriptRecordPtr = NULL;
	return TCL_OK;
    }

    if	((cmd[0] == 's') && (strncmp(cmd, "set", (unsigned) len) == 0)) {
	if (argc != 5) {







|







6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = nextEsPtr) {
	    nextEsPtr = esPtr->nextPtr;
	    Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		    TclChannelEventScriptInvoker, (ClientData) esPtr);
	    Tcl_DecrRefCount(esPtr->scriptPtr);
	    ckfree((char *) esPtr);
	}
	statePtr->scriptRecordPtr = NULL;
	return TCL_OK;
    }

    if	((cmd[0] == 's') && (strncmp(cmd, "set", (unsigned) len) == 0)) {
	if (argc != 5) {
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
TestWrongNumArgsObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, length;
    const char *msg;

    if (objc < 3) {
	/*
	 * Don't use Tcl_WrongNumArgs here, as that is the function
	 * we want to test!
	 */
	Tcl_SetResult(interp, "insufficient arguments", TCL_STATIC);







|







6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
TestWrongNumArgsObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, length;
    char *msg;

    if (objc < 3) {
	/*
	 * Don't use Tcl_WrongNumArgs here, as that is the function
	 * we want to test!
	 */
	Tcl_SetResult(interp, "insufficient arguments", TCL_STATIC);
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
static int
TestGetIndexFromObjStructObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *const ary[] = {
	"a", "b", "c", "d", "e", "f", NULL, NULL
    };
    int idx,target;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue");
	return TCL_ERROR;







|







6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
static int
TestGetIndexFromObjStructObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *ary[] = {
	"a", "b", "c", "d", "e", "f", NULL, NULL
    };
    int idx,target;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue");
	return TCL_ERROR;
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
TestFilesystemObjCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    const char *msg;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "boolean");
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
	return TCL_ERROR;
    }
    if (boolVal) {
	res = Tcl_FSRegister((ClientData)interp, &testReportingFilesystem);
	msg = (res == TCL_OK) ? "registered" : "failed";
    } else {
	res = Tcl_FSUnregister(&testReportingFilesystem);
	msg = (res == TCL_OK) ? "unregistered" : "failed";
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg , -1));
    return res;
}

static int
TestReportInFilesystem(
    Tcl_Obj *pathPtr,
    ClientData *clientDataPtr)







|















|







6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
TestFilesystemObjCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    char *msg;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "boolean");
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
	return TCL_ERROR;
    }
    if (boolVal) {
	res = Tcl_FSRegister((ClientData)interp, &testReportingFilesystem);
	msg = (res == TCL_OK) ? "registered" : "failed";
    } else {
	res = Tcl_FSUnregister(&testReportingFilesystem);
	msg = (res == TCL_OK) ? "unregistered" : "failed";
    }
    Tcl_SetResult(interp, msg, TCL_VOLATILE);
    return res;
}

static int
TestReportInFilesystem(
    Tcl_Obj *pathPtr,
    ClientData *clientDataPtr)
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
TestSimpleFilesystemObjCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    const char *msg;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "boolean");
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
	return TCL_ERROR;
    }
    if (boolVal) {
	res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem);
	msg = (res == TCL_OK) ? "registered" : "failed";
    } else {
	res = Tcl_FSUnregister(&simpleFilesystem);
	msg = (res == TCL_OK) ? "unregistered" : "failed";
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg , -1));
    return res;
}

/*
 * Treats a file name 'simplefs:/foo' by using the file 'foo' in the current
 * (native) directory.
 */







|















|







6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
TestSimpleFilesystemObjCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    char *msg;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "boolean");
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) {
	return TCL_ERROR;
    }
    if (boolVal) {
	res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem);
	msg = (res == TCL_OK) ? "registered" : "failed";
    } else {
	res = Tcl_FSUnregister(&simpleFilesystem);
	msg = (res == TCL_OK) ? "unregistered" : "failed";
    }
    Tcl_SetResult(interp, msg, TCL_VOLATILE);
    return res;
}

/*
 * Treats a file name 'simplefs:/foo' by using the file 'foo' in the current
 * (native) directory.
 */
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
    /* Add one new volume */
    Tcl_Obj *retVal;

    retVal = Tcl_NewStringObj("simplefs:/", -1);
    Tcl_IncrRefCount(retVal);
    return retVal;
}

/*
 * Used to check operations of Tcl_UtfNext.
 *
 * Usage: testutfnext -bytestring $bytes
 */

static int
TestUtfNextCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int numBytes;	/* Number of bytes supplied in the test string */
    int offset;		/* Number of bytes we are permitted to read */
    char *bytes;
    const char *result, *first;
    char buffer[32];
    static const char tobetested[] = "A\xA0\xC0\xC1\xC2\xD0\xE0\xE8\xF2\xF7\xF8\xFE\xFF";
    const char *p = tobetested;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string ?numBytes?");
	return TCL_ERROR;
    }

    bytes = Tcl_GetStringFromObj(objv[1], &numBytes);

    offset = numBytes +TCL_UTF_MAX -1;	/* If no constraint is given, allow
					 * the terminating NUL to limit
					 * operations. */

    if (objc == 3) {
	if (TCL_OK != TclGetIntForIndex(interp, objv[2], numBytes, &offset)) {
	    return TCL_ERROR;
	}
	if (offset < 0) {
	    offset = 0;
	}
	if (offset > numBytes +TCL_UTF_MAX -1) {
	    offset = numBytes +TCL_UTF_MAX -1;
	}
    }

    if (numBytes > (int)sizeof(buffer) - 3) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"testutfnext\" can only handle %d bytes",
		(int)sizeof(buffer) - 4));
	return TCL_ERROR;
    }

    memcpy(buffer + 1, bytes, numBytes);
    buffer[0] = buffer[numBytes + 1] = buffer[numBytes + 2] = buffer[numBytes + 3] = '\xA0';

    if (!Tcl_UtfCharComplete(buffer + 1, offset)) {
	/* Cannot scan a complete sequence from the data */

	Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
	return TCL_OK;
    }

    first = result = TclUtfNext(buffer + 1);
    while ((buffer[0] = *p++) != '\0') {
	/* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */
	result = TclUtfNext(buffer + 1);
	if (first != result) {
	    Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", NULL);
	    return TCL_ERROR;
	}
    }
    p = tobetested;
    while ((buffer[numBytes + 1] = *p++) != '\0') {
	/* Run Tcl_UtfNext with many more possible bytes at src[end], all should give the same result */
	result = TclUtfNext(buffer + 1);
	if (first != result) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Tcl_UtfNext is not supposed to read src[end]\n"
		    "Different result when src[end] is %#x", UCHAR(p[-1])));
	    return TCL_ERROR;
	}
    }

    Tcl_SetObjResult(interp, Tcl_NewIntObj(first - buffer - 1));

    return TCL_OK;
}
/*
 * Used to check operations of Tcl_UtfPrev.
 *
 * Usage: testutfprev $bytes $offset
 */

static int
TestUtfPrevCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int numBytes, offset;
    char *bytes;
    const char *result;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "bytes ?offset?");
	return TCL_ERROR;
    }

    bytes = Tcl_GetStringFromObj(objv[1], &numBytes);

    if (objc == 3) {
	if (TCL_OK != TclGetIntForIndex(interp, objv[2], numBytes, &offset)) {
	    return TCL_ERROR;
	}
	if (offset < 0) {
	    offset = 0;
	}
	if (offset > numBytes) {
	    offset = numBytes;
	}
    } else {
	offset = numBytes;
    }
    result = TclUtfPrev(bytes + offset, bytes);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result - bytes));
    return TCL_OK;
}

/*
 * Used to check correct string-length determining in Tcl_NumUtfChars
 */

static int
TestNumUtfCharsCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 1) {
	int numBytes, len, limit = -1;
	const char *bytes = Tcl_GetStringFromObj(objv[1], &numBytes);

	if (objc > 2) {
	    if (TclGetIntForIndex(interp, objv[2], numBytes, &limit) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (limit > numBytes + 1) {
		limit = numBytes + 1;
	    }
	}
	len = Tcl_NumUtfChars(bytes, limit);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
    }
    return TCL_OK;
}

/*
 * Used to check correct operation of Tcl_UtfFindFirst
 */

static int
TestFindFirstCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 1) {
	int len = -1;

	if (objc > 2) {
	    (void) Tcl_GetIntFromObj(interp, objv[2], &len);
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindFirst(Tcl_GetString(objv[1]), len), -1));
    }
    return TCL_OK;
}

/*
 * Used to check correct operation of Tcl_UtfFindLast
 */

static int
TestFindLastCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 1) {
	int len = -1;

	if (objc > 2) {
	    (void) Tcl_GetIntFromObj(interp, objv[2], &len);
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1));
    }
    return TCL_OK;
}

#if defined(HAVE_CPUID) || defined(_WIN32)
/*
 *----------------------------------------------------------------------
 *
 * TestcpuidCmd --
 *
 *	Retrieves CPU ID information.
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|




|







7088
7089
7090
7091
7092
7093
7094
































































































































7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107





























7108
7109
7110
7111
7112
7113





















7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
    /* Add one new volume */
    Tcl_Obj *retVal;

    retVal = Tcl_NewStringObj("simplefs:/", -1);
    Tcl_IncrRefCount(retVal);
    return retVal;
}

































































































































/*
 * Used to check correct string-length determining in Tcl_NumUtfChars
 */

static int
TestNumUtfCharsCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 1) {





























	int len = -1;

	if (objc > 2) {
	    (void) Tcl_GetStringFromObj(objv[1], &len);
	}
	len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len);





















	Tcl_SetObjResult(interp, Tcl_NewIntObj(len));
    }
    return TCL_OK;
}

#if defined(HAVE_CPUID) || defined(__WIN32__)
/*
 *----------------------------------------------------------------------
 *
 * TestcpuidCmd --
 *
 *	Retrieves CPU ID information.
 *
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416

/*
 * Used to do basic checks of the TCL_HASH_KEY_SYSTEM_HASH flag
 */

static int
TestHashSystemHashCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static Tcl_HashKeyType hkType = {
	TCL_HASH_KEY_TYPE_VERSION, TCL_HASH_KEY_SYSTEM_HASH,
	NULL, NULL, NULL, NULL
    };
    Tcl_HashTable hash;
    Tcl_HashEntry *hPtr;
    int i, isNew, limit = 100;
    (void)dummy;

    if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);

    if (hash.numEntries != 0) {
	Tcl_AppendResult(interp, "non-zero initial size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    for (i=0 ; i<limit ; i++) {
	hPtr = Tcl_CreateHashEntry(&hash, INT2PTR(i), &isNew);
	if (!isNew) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem",-1);
	    Tcl_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(hPtr, INT2PTR(i+42));
    }

    if (hash.numEntries != limit) {
	Tcl_AppendResult(interp, "unexpected maximal size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }







|











<














|






|







7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192

7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221

/*
 * Used to do basic checks of the TCL_HASH_KEY_SYSTEM_HASH flag
 */

static int
TestHashSystemHashCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static Tcl_HashKeyType hkType = {
	TCL_HASH_KEY_TYPE_VERSION, TCL_HASH_KEY_SYSTEM_HASH,
	NULL, NULL, NULL, NULL
    };
    Tcl_HashTable hash;
    Tcl_HashEntry *hPtr;
    int i, isNew, limit = 100;


    if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);

    if (hash.numEntries != 0) {
	Tcl_AppendResult(interp, "non-zero initial size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    for (i=0 ; i<limit ; i++) {
	hPtr = Tcl_CreateHashEntry(&hash, (char *) INT2PTR(i), &isNew);
	if (!isNew) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem",-1);
	    Tcl_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(hPtr, (ClientData) INT2PTR(i+42));
    }

    if (hash.numEntries != limit) {
	Tcl_AppendResult(interp, "unexpected maximal size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463

7464
7465
7466
7467
7468
7469
7470

7471
7472
7473
7474
7475
7476
7477
7478
static int
TestgetintCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int argc,
    const char **argv)
{
    (void)dummy;

    if (argc < 2) {
	Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
	return TCL_ERROR;
    } else {
	int val, i, total=0;


	for (i=1 ; i<argc ; i++) {
	    if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    total += val;
	}

	Tcl_SetObjResult(interp, Tcl_NewIntObj(total));
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *







<
<





>







>
|







7255
7256
7257
7258
7259
7260
7261


7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
static int
TestgetintCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int argc,
    const char **argv)
{


    if (argc < 2) {
	Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
	return TCL_ERROR;
    } else {
	int val, i, total=0;
	char buf[TCL_INTEGER_SPACE];

	for (i=1 ; i<argc ; i++) {
	    if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    total += val;
	}
	TclFormatInt(buf, total);
	Tcl_SetResult(interp, buf, TCL_VOLATILE);
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
	    Tcl_NewStringObj("Tcl_ConcatObj is unsafe:", -1));

    emptyPtr = Tcl_NewObj();

    list1Ptr = Tcl_NewStringObj("foo bar sum", -1);
    Tcl_ListObjLength(NULL, list1Ptr, &len);
    if (list1Ptr->bytes != NULL) {
	ckfree((char *)list1Ptr->bytes);
	list1Ptr->bytes = NULL;
    }

    list2Ptr = Tcl_NewStringObj("eeny meeny", -1);
    Tcl_ListObjLength(NULL, list2Ptr, &len);
    if (list2Ptr->bytes != NULL) {
	ckfree((char *)list2Ptr->bytes);
	list2Ptr->bytes = NULL;
    }

    /*
     * Verify that concat'ing a list obj with one or more empty strings does
     * return a fresh Tcl_Obj (see also [Bug 2055782]).
     */







|






|







7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
	    Tcl_NewStringObj("Tcl_ConcatObj is unsafe:", -1));

    emptyPtr = Tcl_NewObj();

    list1Ptr = Tcl_NewStringObj("foo bar sum", -1);
    Tcl_ListObjLength(NULL, list1Ptr, &len);
    if (list1Ptr->bytes != NULL) {
	ckfree((char *) list1Ptr->bytes);
	list1Ptr->bytes = NULL;
    }

    list2Ptr = Tcl_NewStringObj("eeny meeny", -1);
    Tcl_ListObjLength(NULL, list2Ptr, &len);
    if (list2Ptr->bytes != NULL) {
	ckfree((char *) list2Ptr->bytes);
	list2Ptr->bytes = NULL;
    }

    /*
     * Verify that concat'ing a list obj with one or more empty strings does
     * return a fresh Tcl_Obj (see also [Bug 2055782]).
     */

Changes to generic/tclTestObj.c.

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], !mp_isodd(&bignumValue));
	} else {
	    SetVarToObj(varIndex, Tcl_NewIntObj(!mp_isodd(&bignumValue)));
	}
	mp_clear(&bignumValue);
	break;

    case BIGNUM_RADIXSIZE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");







|

|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], mp_iseven(&bignumValue));
	} else {
	    SetVarToObj(varIndex, Tcl_NewIntObj(mp_iseven(&bignumValue)));
	}
	mp_clear(&bignumValue);
	break;

    case BIGNUM_RADIXSIZE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");

Changes to generic/tclTimer.c.

878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id|command");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    commandPtr = objv[2];
	} else {
	    commandPtr = Tcl_ConcatObj(objc-2, objv+2);
	}
	command = Tcl_GetStringFromObj(commandPtr, &length);
	for (afterPtr = assocPtr->firstAfterPtr;  afterPtr != NULL;
		afterPtr = afterPtr->nextPtr) {
	    tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr,
		    &tempLength);
	    if ((length == tempLength)







|







878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id|command");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    commandPtr = objv[2];
	} else {
	    commandPtr = Tcl_ConcatObj(objc-2, objv+2);;
	}
	command = Tcl_GetStringFromObj(commandPtr, &length);
	for (afterPtr = assocPtr->firstAfterPtr;  afterPtr != NULL;
		afterPtr = afterPtr->nextPtr) {
	    tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr,
		    &tempLength);
	    if ((length == tempLength)

Changes to generic/tclTomMath.decls.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# tclTomMath.decls --
#
#	This file contains the declarations for the functions in 'libtommath'
#	that are contained within the Tcl library.  This file is used to
#	generate the 'tclTomMathDecls.h' and 'tclStubInit.c' files.

#
# If you edit this file, advance the revision number (and the epoch
# if the new stubs are not backward compatible) in tclTomMathDecls.h
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclTomMath
scspec EXTERN

# Declare each of the functions in the Tcl tommath interface

declare 0 {
    int TclBN_epoch(void)
}
declare 1 {
    int TclBN_revision(void)
}

declare 2 {
    int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 3 {
    int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 4 {
    int TclBN_mp_and(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 5 {
    void TclBN_mp_clamp(mp_int *a)
}
declare 6 {
    void TclBN_mp_clear(mp_int *a)
}
declare 7 {
    void TclBN_mp_clear_multi(mp_int *a, ...)
}
declare 8 {
    int TclBN_mp_cmp(const mp_int *a, const mp_int *b)
}
declare 9 {
    int TclBN_mp_cmp_d(const mp_int *a, mp_digit b)
}
declare 10 {
    int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b)
}
declare 11 {
    int TclBN_mp_copy(mp_int *a, mp_int *b)
}
declare 12 {
    int TclBN_mp_count_bits(mp_int *a)
}
declare 13 {
    int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
}
declare 14 {
    int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
}
declare 15 {
    int TclBN_mp_div_2(mp_int *a, mp_int *q)
}
declare 16 {
    int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 17 {
    int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r)
}
declare 18 {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
    int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 20 {
    int TclBN_mp_grow(mp_int *a, int size)
}
declare 21 {
    int TclBN_mp_init(mp_int *a)
}
declare 22 {
    int TclBN_mp_init_copy(mp_int *a, mp_int *b)
}
declare 23 {
    int TclBN_mp_init_multi(mp_int *a, ...)
}
declare 24 {
    int TclBN_mp_init_set(mp_int *a, mp_digit b)
}
declare 25 {
    int TclBN_mp_init_size(mp_int *a, int size)
}
declare 26 {
    int TclBN_mp_lshd(mp_int *a, int shift)
}
declare 27 {
    int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r)
}
declare 28 {
    int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r)
}
declare 29 {
    int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p)
}
declare 30 {
    int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p)
}
declare 31 {
    int TclBN_mp_mul_2(mp_int *a, mp_int *p)
}
declare 32 {
    int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p)
}
declare 33 {
    int TclBN_mp_neg(mp_int *a, mp_int *b)
}
declare 34 {
    int TclBN_mp_or(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 35 {
    int TclBN_mp_radix_size(mp_int *a, int radix, int *size)
}
declare 36 {
    int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
}
declare 37 {
    void TclBN_mp_rshd(mp_int *a, int shift)
}
declare 38 {
    int TclBN_mp_shrink(mp_int *a)
}
declare 39 {
    void TclBN_mp_set(mp_int *a, mp_digit b)
}
declare 40 {
    int TclBN_mp_sqr(mp_int *a, mp_int *b)
}
declare 41 {
    int TclBN_mp_sqrt(mp_int *a, mp_int *b)
}
declare 42 {
    int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 43 {
    int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 44 {
    int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b)
}
declare 45 {
    int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b,
	    unsigned long *outlen)
}
declare 46 {
    int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen)
}
declare 47 {
    int TclBN_mp_unsigned_bin_size(mp_int *a)
}
declare 48 {
    int TclBN_mp_xor(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 49 {
    void TclBN_mp_zero(mp_int *a)
}

# internal routines to libtommath - should not be called but must be
# exported to accommodate the "tommath" extension

declare 50 {
    void TclBN_reverse(unsigned char *s, int len)
}
declare 51 {
    int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 52 {
    int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 53 {
    int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 54 {
    int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b)
}
declare 55 {
    int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 56 {
    int TclBN_mp_toom_sqr(mp_int *a, mp_int *b)
}
declare 57 {
    int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 58 {
    int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 59 {
    int TclBN_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 60 {
    int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 61 {
    int TclBN_mp_init_set_int(mp_int *a, unsigned long i)
}
declare 62 {
    int TclBN_mp_set_int(mp_int *a, unsigned long i)
}
declare 63 {
    int TclBN_mp_cnt_lsb(mp_int *a)
}
declare 80 {
    void TclUnusedStubEntry(void)
}


# Local Variables:
# mode: tcl
# End:


|
|
|
>














|



|


|



|


|


|
|

|


|


|


|
|

|
|

|
|

|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|
|

|


|


|


|


|


|


|


|


|


|


|



|


|


|
|

|






|


|


|


|


|


|


|


|


|


|


|











<
<
<
<
<
<
<
<
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222








# tclTomMath.decls --
#
#	This file contains the declarations for the functions in
#	'libtommath' that are contained within the Tcl library.
#	This file is used to generate the 'tclTomMathDecls.h' and
#	'tclStubInit.c' files.
#
# If you edit this file, advance the revision number (and the epoch
# if the new stubs are not backward compatible) in tclTomMathDecls.h
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclTomMath
# hooks {tclTomMathInt}

# Declare each of the functions in the Tcl tommath interface

declare 0 generic {
    int TclBN_epoch(void)
}
declare 1 generic {
    int TclBN_revision(void)
}

declare 2 generic {
    int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 3 generic {
    int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 4 generic {
    int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c)
}
declare 5 generic {
    void TclBN_mp_clamp(mp_int *a)
}
declare 6 generic {
    void TclBN_mp_clear(mp_int *a)
}
declare 7 generic {
    void TclBN_mp_clear_multi(mp_int *a, ...)
}
declare 8 generic {
    int TclBN_mp_cmp(mp_int *a, mp_int *b)
}
declare 9 generic {
    int TclBN_mp_cmp_d(mp_int *a, mp_digit b)
}
declare 10 generic {
    int TclBN_mp_cmp_mag(mp_int *a, mp_int *b)
}
declare 11 generic {
    int TclBN_mp_copy(mp_int *a, mp_int *b)
}
declare 12 generic {
    int TclBN_mp_count_bits(mp_int *a)
}
declare 13 generic {
    int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
}
declare 14 generic {
    int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
}
declare 15 generic {
    int TclBN_mp_div_2(mp_int *a, mp_int *q)
}
declare 16 generic {
    int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q, mp_int *r)
}
declare 17 generic {
    int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r)
}
declare 18 generic {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 generic {
    int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 20 generic {
    int TclBN_mp_grow(mp_int *a, int size)
}
declare 21 generic {
    int TclBN_mp_init(mp_int *a)
}
declare 22 generic {
    int TclBN_mp_init_copy(mp_int *a, mp_int *b)
}
declare 23 generic {
    int TclBN_mp_init_multi(mp_int *a, ...)
}
declare 24 generic {
    int TclBN_mp_init_set(mp_int *a, mp_digit b)
}
declare 25 generic {
    int TclBN_mp_init_size(mp_int *a, int size)
}
declare 26 generic {
    int TclBN_mp_lshd(mp_int *a, int shift)
}
declare 27 generic {
    int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r)
}
declare 28 generic {
    int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r)
}
declare 29 generic {
    int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p)
}
declare 30 generic {
    int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p)
}
declare 31 generic {
    int TclBN_mp_mul_2(mp_int *a, mp_int *p)
}
declare 32 generic {
    int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p)
}
declare 33 generic {
    int TclBN_mp_neg(mp_int *a, mp_int *b)
}
declare 34 generic {
    int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c)
}
declare 35 generic {
    int TclBN_mp_radix_size(mp_int *a, int radix, int *size)
}
declare 36 generic {
    int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
}
declare 37 generic {
    void TclBN_mp_rshd(mp_int *a, int shift)
}
declare 38 generic {
    int TclBN_mp_shrink(mp_int *a)
}
declare 39 generic {
    void TclBN_mp_set(mp_int *a, mp_digit b)
}
declare 40 generic {
    int TclBN_mp_sqr(mp_int *a, mp_int *b)
}
declare 41 generic {
    int TclBN_mp_sqrt(mp_int *a, mp_int *b)
}
declare 42 generic {
    int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 43 generic {
    int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 44 generic {
    int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b)
}
declare 45 generic {
    int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b,
	    unsigned long *outlen)
}
declare 46 generic {
    int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen)
}
declare 47 generic {
    int TclBN_mp_unsigned_bin_size(mp_int *a)
}
declare 48 generic {
    int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c)
}
declare 49 generic {
    void TclBN_mp_zero(mp_int *a)
}

# internal routines to libtommath - should not be called but must be
# exported to accommodate the "tommath" extension

declare 50 generic {
    void TclBN_reverse(unsigned char *s, int len)
}
declare 51 generic {
    int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 52 generic {
    int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 53 generic {
    int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 54 generic {
    int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b)
}
declare 55 generic {
    int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
}
declare 56 generic {
    int TclBN_mp_toom_sqr(mp_int *a, mp_int *b)
}
declare 57 generic {
    int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c)
}
declare 58 generic {
    int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
}
declare 59 generic {
    int TclBN_s_mp_sqr(mp_int *a, mp_int *b)
}
declare 60 generic {
    int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c)
}
declare 61 {
    int TclBN_mp_init_set_int(mp_int *a, unsigned long i)
}
declare 62 {
    int TclBN_mp_set_int(mp_int *a, unsigned long i)
}
declare 63 {
    int TclBN_mp_cnt_lsb(mp_int *a)
}








Changes to generic/tclTomMath.h.

1
2
3












4
5
6
7
8
9
10
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */













#ifndef BN_H_
#define BN_H_

#include <tclTomMathDecls.h>
#ifndef MODULE_SCOPE
#define MODULE_SCOPE extern
#endif
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>







1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#ifndef BN_H_
#define BN_H_

#include <tclTomMathDecls.h>
#ifndef MODULE_SCOPE
#define MODULE_SCOPE extern
#endif
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
120
121
122
#define MP_DIGIT_DECLARED
#endif
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */

   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__)
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

#ifndef MP_DIGIT_DECLARED
   typedef unsigned int      mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef ulong64            mp_word;

#ifdef MP_31BIT
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif
#endif

/* define heap macros */
#if 0 /* these are macros in tclTomMathDecls.h */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);







|


|














|






|






|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#define MP_DIGIT_DECLARED
#endif
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */
   
   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__) 
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

#ifndef MP_DIGIT_DECLARED
   typedef unsigned int      mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef ulong64            mp_word;

#ifdef MP_31BIT   
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif   
#endif

/* define heap macros */
#if 0 /* these are macros in tclTomMathDecls.h */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC 
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156


157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240




241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

typedef int mp_sign;
#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */
typedef int mp_ord;
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */
typedef int mp_bool;
#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */
typedef int mp_err;
#define MP_OKAY       0   /* ok result */
#define MP_ERR        -1  /* unknown error */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL
#define MP_ITER       -4  /* Max. iterations reached */



/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

/* tunable cutoffs */


#if defined(BUILD_tcl) || !defined(_WIN32)
MODULE_SCOPE int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;
#endif

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
#   ifndef MP_LOW_MEM
#      define MP_PREC 32        /* default digits of precision */
#   elif defined(MP_8BIT)
#      define MP_PREC 16        /* default digits of precision */
#   else
#      define MP_PREC 8         /* default digits of precision */
#   endif
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/*
 * MP_WUR - warn unused result
 * ---------------------------
 *
 * The result of functions annotated with MP_WUR must be
 * checked and cannot be ignored.
 *
 * Most functions in libtommath return an error code.
 * This error code must be checked in order to prevent crashes or invalid
 * results.
 *
 * If you still want to avoid the error checks for quick and dirty programs
 * without robustness guarantees, you can `#define MP_WUR` before including
 * tommath.h, disabling the warnings.
 */
#ifndef MP_WUR
#  if defined(__GNUC__) && __GNUC__ >= 4
#     define MP_WUR __attribute__((warn_unused_result))
#  else
#     define MP_WUR
#  endif
#endif

#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301)
#  define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
#  define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s)
#  define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s)
#elif defined(_MSC_VER) && _MSC_VER >= 1500
#  define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x))
#  define MP_DEPRECATED_PRAGMA(s) __pragma(message(s))
#else
#  define MP_DEPRECATED
#  define MP_DEPRECATED_PRAGMA(s)
#endif

#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* the infamous mp_int structure */
#ifndef MP_INT_DECLARED
#define MP_INT_DECLARED
typedef struct mp_int mp_int;
#endif
struct mp_int {
    int used, alloc, sign;
    mp_digit *dp;
};

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);






/* error code to char* string */
/*
const char *mp_error_to_string(mp_err code);
*/

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
/*
mp_err mp_init(mp_int *a);
*/

/* free a bignum */
/*
void mp_clear(mp_int *a);
*/

/* init a null terminated series of arguments */
/*
mp_err mp_init_multi(mp_int *mp, ...);
*/

/* clear a null terminated series of arguments */
/*
void mp_clear_multi(mp_int *mp, ...);
*/

/* exchange two ints */
/*
void mp_exch(mp_int *a, mp_int *b);
*/

/* shrink ram required for a bignum */
/*
mp_err mp_shrink(mp_int *a);
*/

/* grow an int to a given size */
/*
mp_err mp_grow(mp_int *a, int size);
*/

/* init to a given number of digits */
/*
mp_err mp_init_size(mp_int *a, int size);
*/

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)

/* set to zero */
/*
void mp_zero(mp_int *a);
*/

/* set to a digit */
/*
void mp_set(mp_int *a, mp_digit b);
*/

/* set a 32-bit const */
/*
int mp_set_int(mp_int *a, unsigned long b);
*/

/* set a platform dependent unsigned long value */
/*
int mp_set_long(mp_int *a, unsigned long b);
*/

/* set a platform dependent unsigned long long value */
/*
int mp_set_long_long(mp_int *a, unsigned long long b);
*/

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
/*
int mp_init_set (mp_int * a, mp_digit b);
*/







<
<
|
<



|
|
|
|

<



|
>
>






|

>












|
|
<
<
|
|
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













>
>
>
>



|





|









|














|




|




|






<
















<
<
<
<
<
<
<
<
<
<







144
145
146
147
148
149
150


151

152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188


189
190
191
192
193
194
195
196







































197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280










281
282
283
284
285
286
287
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK



/* equalities */

#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */

#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */

#define MP_OKAY       0   /* ok result */

#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL

#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

typedef int           mp_err;

/* you'll have to tune these... */
#if defined(BUILD_tcl) || !defined(_WIN32)
MODULE_SCOPE int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;
#endif

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
   #ifndef MP_LOW_MEM
      #define MP_PREC                 32     /* default digits of precision */


   #else
      #define MP_PREC                 8      /* default digits of precision */
   #endif   
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))








































/* the infamous mp_int structure */
#ifndef MP_INT_DECLARED
#define MP_INT_DECLARED
typedef struct mp_int mp_int;
#endif
struct mp_int {
    int used, alloc, sign;
    mp_digit *dp;
};

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
/*
char *mp_error_to_string(int code);
*/

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
/*
int mp_init(mp_int *a);
*/

/* free a bignum */
/*
void mp_clear(mp_int *a);
*/

/* init a null terminated series of arguments */
/*
int mp_init_multi(mp_int *mp, ...);
*/

/* clear a null terminated series of arguments */
/*
void mp_clear_multi(mp_int *mp, ...);
*/

/* exchange two ints */
/*
void mp_exch(mp_int *a, mp_int *b);
*/

/* shrink ram required for a bignum */
/*
int mp_shrink(mp_int *a);
*/

/* grow an int to a given size */
/*
int mp_grow(mp_int *a, int size);
*/

/* init to a given number of digits */
/*
int mp_init_size(mp_int *a, int size);
*/

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)


/* set to zero */
/*
void mp_zero(mp_int *a);
*/

/* set to a digit */
/*
void mp_set(mp_int *a, mp_digit b);
*/

/* set a 32-bit const */
/*
int mp_set_int(mp_int *a, unsigned long b);
*/











/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
/*
int mp_init_set (mp_int * a, mp_digit b);
*/
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
int mp_prime_is_divisible(mp_int *a, int *result);
*/

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result);
*/

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result);
*/

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96
 */
/*
int mp_prime_rabin_miller_trials(int size);
*/

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
/*
mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result);
*/

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
/*
mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style);
*/

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 *
 *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
 *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)

 *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
/*







|






|



|













|








|



|












|
|
|
>
|







635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
int mp_prime_is_divisible(mp_int *a, int *result);
*/

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
*/

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
/*
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
*/

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96 
 */
/*
int mp_prime_rabin_miller_trials(int size);
*/

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
/*
int mp_prime_is_prime(mp_int *a, int t, int *result);
*/

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
/*
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
*/

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4 
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
/*
863
864
865
866
867
868
869
870
871
872
873
*/

#if defined(BUILD_tcl) || !defined(_WIN32)
MODULE_SCOPE const char *mp_s_rmap;
#endif

#ifdef __cplusplus
}
#endif

#endif







|



826
827
828
829
830
831
832
833
834
835
836
*/

#if defined(BUILD_tcl) || !defined(_WIN32)
MODULE_SCOPE const char *mp_s_rmap;
#endif

#ifdef __cplusplus
   }
#endif

#endif

Changes to generic/tclTomMathDecls.h.

40
41
42
43
44
45
46







47
48
49
50
51
52
53
54
55
56
57
58
59
/* unused - no macro */

#define XMALLOC(x) TclBNAlloc(x)
#define XFREE(x) TclBNFree(x)
#define XREALLOC(x,n) TclBNRealloc(x,n)
#define XCALLOC(n,x) TclBNCalloc(n,x)








#define bn_reverse TclBN_reverse
#define s_mp_reverse TclBN_reverse
#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
#define s_mp_mul_digs_fast TclBN_fast_s_mp_mul_digs
#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
#define s_mp_sqr_fast TclBN_fast_s_mp_sqr
#define mp_add TclBN_mp_add
#define mp_add_d TclBN_mp_add_d
#define mp_and TclBN_mp_and
#define mp_clamp TclBN_mp_clamp
#define mp_clear TclBN_mp_clear
#define mp_clear_multi TclBN_mp_clear_multi
#define mp_cmp TclBN_mp_cmp







>
>
>
>
>
>
>

<

<

<







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55

56

57
58
59
60
61
62
63
/* unused - no macro */

#define XMALLOC(x) TclBNAlloc(x)
#define XFREE(x) TclBNFree(x)
#define XREALLOC(x,n) TclBNRealloc(x,n)
#define XCALLOC(n,x) TclBNCalloc(n,x)

/* Rename the global symbols in libtommath to avoid linkage conflicts */

#define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff
#define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff
#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff

#define bn_reverse TclBN_reverse

#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs

#define fast_s_mp_sqr TclBN_fast_s_mp_sqr

#define mp_add TclBN_mp_add
#define mp_add_d TclBN_mp_add_d
#define mp_and TclBN_mp_and
#define mp_clamp TclBN_mp_clamp
#define mp_clear TclBN_mp_clear
#define mp_clear_multi TclBN_mp_clear_multi
#define mp_cmp TclBN_mp_cmp
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#define mp_init TclBN_mp_init
#define mp_init_copy TclBN_mp_init_copy
#define mp_init_multi TclBN_mp_init_multi
#define mp_init_set TclBN_mp_init_set
#define mp_init_set_int TclBN_mp_init_set_int
#define mp_init_size TclBN_mp_init_size
#define mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define s_mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
#define s_mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
#define mp_lshd TclBN_mp_lshd
#define mp_mod TclBN_mp_mod
#define mp_mod_2d TclBN_mp_mod_2d
#define mp_mul TclBN_mp_mul
#define mp_mul_2 TclBN_mp_mul_2
#define mp_mul_2d TclBN_mp_mul_2d
#define mp_mul_d TclBN_mp_mul_d







<

<







77
78
79
80
81
82
83

84

85
86
87
88
89
90
91
#define mp_init TclBN_mp_init
#define mp_init_copy TclBN_mp_init_copy
#define mp_init_multi TclBN_mp_init_multi
#define mp_init_set TclBN_mp_init_set
#define mp_init_set_int TclBN_mp_init_set_int
#define mp_init_size TclBN_mp_init_size
#define mp_karatsuba_mul TclBN_mp_karatsuba_mul

#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr

#define mp_lshd TclBN_mp_lshd
#define mp_mod TclBN_mp_mod
#define mp_mod_2d TclBN_mp_mod_2d
#define mp_mul TclBN_mp_mul
#define mp_mul_2 TclBN_mp_mul_2
#define mp_mul_2d TclBN_mp_mul_2d
#define mp_mul_d TclBN_mp_mul_d
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#define mp_sqr TclBN_mp_sqr
#define mp_sqrt TclBN_mp_sqrt
#define mp_sub TclBN_mp_sub
#define mp_sub_d TclBN_mp_sub_d
#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
#define mp_toom_mul TclBN_mp_toom_mul
#define s_mp_toom_mul TclBN_mp_toom_mul
#define mp_toom_sqr TclBN_mp_toom_sqr
#define s_mp_toom_sqr TclBN_mp_toom_sqr
#define mp_toradix_n TclBN_mp_toradix_n
#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size
#define mp_xor TclBN_mp_xor
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_mul_digs TclBN_s_mp_mul_digs
#define s_mp_sqr TclBN_s_mp_sqr







<

<







101
102
103
104
105
106
107

108

109
110
111
112
113
114
115
#define mp_sqr TclBN_mp_sqr
#define mp_sqrt TclBN_mp_sqrt
#define mp_sub TclBN_mp_sub
#define mp_sub_d TclBN_mp_sub_d
#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
#define mp_toom_mul TclBN_mp_toom_mul

#define mp_toom_sqr TclBN_mp_toom_sqr

#define mp_toradix_n TclBN_mp_toradix_n
#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size
#define mp_xor TclBN_mp_xor
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_mul_digs TclBN_s_mp_mul_digs
#define s_mp_sqr TclBN_s_mp_sqr
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#define TclBN_mp_add_d_TCL_DECLARED
/* 3 */
EXTERN int		TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c);
#endif
#ifndef TclBN_mp_and_TCL_DECLARED
#define TclBN_mp_and_TCL_DECLARED
/* 4 */
EXTERN int		TclBN_mp_and(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_clamp_TCL_DECLARED
#define TclBN_mp_clamp_TCL_DECLARED
/* 5 */
EXTERN void		TclBN_mp_clamp(mp_int *a);
#endif
#ifndef TclBN_mp_clear_TCL_DECLARED
#define TclBN_mp_clear_TCL_DECLARED
/* 6 */
EXTERN void		TclBN_mp_clear(mp_int *a);
#endif
#ifndef TclBN_mp_clear_multi_TCL_DECLARED
#define TclBN_mp_clear_multi_TCL_DECLARED
/* 7 */
EXTERN void		TclBN_mp_clear_multi(mp_int *a, ...);
#endif
#ifndef TclBN_mp_cmp_TCL_DECLARED
#define TclBN_mp_cmp_TCL_DECLARED
/* 8 */
EXTERN int		TclBN_mp_cmp(CONST mp_int *a, CONST mp_int *b);
#endif
#ifndef TclBN_mp_cmp_d_TCL_DECLARED
#define TclBN_mp_cmp_d_TCL_DECLARED
/* 9 */
EXTERN int		TclBN_mp_cmp_d(CONST mp_int *a, mp_digit b);
#endif
#ifndef TclBN_mp_cmp_mag_TCL_DECLARED
#define TclBN_mp_cmp_mag_TCL_DECLARED
/* 10 */
EXTERN int		TclBN_mp_cmp_mag(CONST mp_int *a, CONST mp_int *b);
#endif
#ifndef TclBN_mp_copy_TCL_DECLARED
#define TclBN_mp_copy_TCL_DECLARED
/* 11 */
EXTERN int		TclBN_mp_copy(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_count_bits_TCL_DECLARED







|
<



















|




|




|







161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#define TclBN_mp_add_d_TCL_DECLARED
/* 3 */
EXTERN int		TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c);
#endif
#ifndef TclBN_mp_and_TCL_DECLARED
#define TclBN_mp_and_TCL_DECLARED
/* 4 */
EXTERN int		TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_clamp_TCL_DECLARED
#define TclBN_mp_clamp_TCL_DECLARED
/* 5 */
EXTERN void		TclBN_mp_clamp(mp_int *a);
#endif
#ifndef TclBN_mp_clear_TCL_DECLARED
#define TclBN_mp_clear_TCL_DECLARED
/* 6 */
EXTERN void		TclBN_mp_clear(mp_int *a);
#endif
#ifndef TclBN_mp_clear_multi_TCL_DECLARED
#define TclBN_mp_clear_multi_TCL_DECLARED
/* 7 */
EXTERN void		TclBN_mp_clear_multi(mp_int *a, ...);
#endif
#ifndef TclBN_mp_cmp_TCL_DECLARED
#define TclBN_mp_cmp_TCL_DECLARED
/* 8 */
EXTERN int		TclBN_mp_cmp(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_cmp_d_TCL_DECLARED
#define TclBN_mp_cmp_d_TCL_DECLARED
/* 9 */
EXTERN int		TclBN_mp_cmp_d(mp_int *a, mp_digit b);
#endif
#ifndef TclBN_mp_cmp_mag_TCL_DECLARED
#define TclBN_mp_cmp_mag_TCL_DECLARED
/* 10 */
EXTERN int		TclBN_mp_cmp_mag(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_copy_TCL_DECLARED
#define TclBN_mp_copy_TCL_DECLARED
/* 11 */
EXTERN int		TclBN_mp_copy(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_count_bits_TCL_DECLARED
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#define TclBN_mp_neg_TCL_DECLARED
/* 33 */
EXTERN int		TclBN_mp_neg(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_or_TCL_DECLARED
#define TclBN_mp_or_TCL_DECLARED
/* 34 */
EXTERN int		TclBN_mp_or(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_radix_size_TCL_DECLARED
#define TclBN_mp_radix_size_TCL_DECLARED
/* 35 */
EXTERN int		TclBN_mp_radix_size(mp_int *a, int radix, int *size);
#endif
#ifndef TclBN_mp_read_radix_TCL_DECLARED







|
<







314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
#define TclBN_mp_neg_TCL_DECLARED
/* 33 */
EXTERN int		TclBN_mp_neg(mp_int *a, mp_int *b);
#endif
#ifndef TclBN_mp_or_TCL_DECLARED
#define TclBN_mp_or_TCL_DECLARED
/* 34 */
EXTERN int		TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_radix_size_TCL_DECLARED
#define TclBN_mp_radix_size_TCL_DECLARED
/* 35 */
EXTERN int		TclBN_mp_radix_size(mp_int *a, int radix, int *size);
#endif
#ifndef TclBN_mp_read_radix_TCL_DECLARED
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
#define TclBN_mp_unsigned_bin_size_TCL_DECLARED
/* 47 */
EXTERN int		TclBN_mp_unsigned_bin_size(mp_int *a);
#endif
#ifndef TclBN_mp_xor_TCL_DECLARED
#define TclBN_mp_xor_TCL_DECLARED
/* 48 */
EXTERN int		TclBN_mp_xor(CONST mp_int *a, CONST mp_int *b,
				mp_int *c);
#endif
#ifndef TclBN_mp_zero_TCL_DECLARED
#define TclBN_mp_zero_TCL_DECLARED
/* 49 */
EXTERN void		TclBN_mp_zero(mp_int *a);
#endif
#ifndef TclBN_reverse_TCL_DECLARED







|
<







387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
#define TclBN_mp_unsigned_bin_size_TCL_DECLARED
/* 47 */
EXTERN int		TclBN_mp_unsigned_bin_size(mp_int *a);
#endif
#ifndef TclBN_mp_xor_TCL_DECLARED
#define TclBN_mp_xor_TCL_DECLARED
/* 48 */
EXTERN int		TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c);

#endif
#ifndef TclBN_mp_zero_TCL_DECLARED
#define TclBN_mp_zero_TCL_DECLARED
/* 49 */
EXTERN void		TclBN_mp_zero(mp_int *a);
#endif
#ifndef TclBN_reverse_TCL_DECLARED
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
EXTERN int		TclBN_mp_set_int(mp_int *a, unsigned long i);
#endif
#ifndef TclBN_mp_cnt_lsb_TCL_DECLARED
#define TclBN_mp_cnt_lsb_TCL_DECLARED
/* 63 */
EXTERN int		TclBN_mp_cnt_lsb(mp_int *a);
#endif
/* Slot 64 is reserved */
/* Slot 65 is reserved */
/* Slot 66 is reserved */
/* Slot 67 is reserved */
/* Slot 68 is reserved */
/* Slot 69 is reserved */
/* Slot 70 is reserved */
/* Slot 71 is reserved */
/* Slot 72 is reserved */
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
/* Slot 76 is reserved */
/* Slot 77 is reserved */
/* Slot 78 is reserved */
/* Slot 79 is reserved */
#ifndef TclUnusedStubEntry_TCL_DECLARED
#define TclUnusedStubEntry_TCL_DECLARED
/* 80 */
EXTERN void		TclUnusedStubEntry(void);
#endif

typedef struct TclTomMathStubs {
    int magic;
    struct TclTomMathStubHooks *hooks;

    int (*tclBN_epoch) (void); /* 0 */
    int (*tclBN_revision) (void); /* 1 */
    int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */
    int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */
    int (*tclBN_mp_and) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 4 */
    void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
    void (*tclBN_mp_clear) (mp_int *a); /* 6 */
    void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
    int (*tclBN_mp_cmp) (CONST mp_int *a, CONST mp_int *b); /* 8 */
    int (*tclBN_mp_cmp_d) (CONST mp_int *a, mp_digit b); /* 9 */
    int (*tclBN_mp_cmp_mag) (CONST mp_int *a, CONST mp_int *b); /* 10 */
    int (*tclBN_mp_copy) (mp_int *a, mp_int *b); /* 11 */
    int (*tclBN_mp_count_bits) (mp_int *a); /* 12 */
    int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */
    int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */
    int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */
    int (*tclBN_mp_div_2d) (mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */
    int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









|



|
|
|







467
468
469
470
471
472
473





















474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
EXTERN int		TclBN_mp_set_int(mp_int *a, unsigned long i);
#endif
#ifndef TclBN_mp_cnt_lsb_TCL_DECLARED
#define TclBN_mp_cnt_lsb_TCL_DECLARED
/* 63 */
EXTERN int		TclBN_mp_cnt_lsb(mp_int *a);
#endif






















typedef struct TclTomMathStubs {
    int magic;
    struct TclTomMathStubHooks *hooks;

    int (*tclBN_epoch) (void); /* 0 */
    int (*tclBN_revision) (void); /* 1 */
    int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */
    int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */
    int (*tclBN_mp_and) (mp_int *a, mp_int *b, mp_int *c); /* 4 */
    void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
    void (*tclBN_mp_clear) (mp_int *a); /* 6 */
    void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
    int (*tclBN_mp_cmp) (mp_int *a, mp_int *b); /* 8 */
    int (*tclBN_mp_cmp_d) (mp_int *a, mp_digit b); /* 9 */
    int (*tclBN_mp_cmp_mag) (mp_int *a, mp_int *b); /* 10 */
    int (*tclBN_mp_copy) (mp_int *a, mp_int *b); /* 11 */
    int (*tclBN_mp_count_bits) (mp_int *a); /* 12 */
    int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */
    int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */
    int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */
    int (*tclBN_mp_div_2d) (mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */
    int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
    int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */
    int (*tclBN_mp_mod_2d) (mp_int *a, int b, mp_int *r); /* 28 */
    int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */
    int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */
    int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */
    int (*tclBN_mp_mul_2d) (mp_int *a, int d, mp_int *p); /* 32 */
    int (*tclBN_mp_neg) (mp_int *a, mp_int *b); /* 33 */
    int (*tclBN_mp_or) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 34 */
    int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */
    int (*tclBN_mp_read_radix) (mp_int *a, CONST char *str, int radix); /* 36 */
    void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
    int (*tclBN_mp_shrink) (mp_int *a); /* 38 */
    void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
    int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */
    int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */
    int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */
    int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */
    int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */
    int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */
    int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */
    int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */
    int (*tclBN_mp_xor) (CONST mp_int *a, CONST mp_int *b, mp_int *c); /* 48 */
    void (*tclBN_mp_zero) (mp_int *a); /* 49 */
    void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */
    int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */
    int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */
    int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */
    int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */
    int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */
    int (*tclBN_mp_toom_sqr) (mp_int *a, mp_int *b); /* 56 */
    int (*tclBN_s_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 57 */
    int (*tclBN_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 58 */
    int (*tclBN_s_mp_sqr) (mp_int *a, mp_int *b); /* 59 */
    int (*tclBN_s_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 60 */
    int (*tclBN_mp_init_set_int) (mp_int *a, unsigned long i); /* 61 */
    int (*tclBN_mp_set_int) (mp_int *a, unsigned long i); /* 62 */
    int (*tclBN_mp_cnt_lsb) (mp_int *a); /* 63 */
    VOID *reserved64;
    VOID *reserved65;
    VOID *reserved66;
    VOID *reserved67;
    VOID *reserved68;
    VOID *reserved69;
    VOID *reserved70;
    VOID *reserved71;
    VOID *reserved72;
    VOID *reserved73;
    VOID *reserved74;
    VOID *reserved75;
    VOID *reserved76;
    VOID *reserved77;
    VOID *reserved78;
    VOID *reserved79;
    void (*tclUnusedStubEntry) (void); /* 80 */
} TclTomMathStubs;

extern TclTomMathStubs *tclTomMathStubsPtr;

#ifdef __cplusplus
}
#endif







|













|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

















543
544
545
546
547
548
549
    int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */
    int (*tclBN_mp_mod_2d) (mp_int *a, int b, mp_int *r); /* 28 */
    int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */
    int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */
    int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */
    int (*tclBN_mp_mul_2d) (mp_int *a, int d, mp_int *p); /* 32 */
    int (*tclBN_mp_neg) (mp_int *a, mp_int *b); /* 33 */
    int (*tclBN_mp_or) (mp_int *a, mp_int *b, mp_int *c); /* 34 */
    int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */
    int (*tclBN_mp_read_radix) (mp_int *a, CONST char *str, int radix); /* 36 */
    void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
    int (*tclBN_mp_shrink) (mp_int *a); /* 38 */
    void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
    int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */
    int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */
    int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */
    int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */
    int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */
    int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */
    int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */
    int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */
    int (*tclBN_mp_xor) (mp_int *a, mp_int *b, mp_int *c); /* 48 */
    void (*tclBN_mp_zero) (mp_int *a); /* 49 */
    void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */
    int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */
    int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */
    int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */
    int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */
    int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */
    int (*tclBN_mp_toom_sqr) (mp_int *a, mp_int *b); /* 56 */
    int (*tclBN_s_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 57 */
    int (*tclBN_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 58 */
    int (*tclBN_s_mp_sqr) (mp_int *a, mp_int *b); /* 59 */
    int (*tclBN_s_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 60 */
    int (*tclBN_mp_init_set_int) (mp_int *a, unsigned long i); /* 61 */
    int (*tclBN_mp_set_int) (mp_int *a, unsigned long i); /* 62 */
    int (*tclBN_mp_cnt_lsb) (mp_int *a); /* 63 */

















} TclTomMathStubs;

extern TclTomMathStubs *tclTomMathStubsPtr;

#ifdef __cplusplus
}
#endif
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
#define TclBN_mp_set_int \
	(tclTomMathStubsPtr->tclBN_mp_set_int) /* 62 */
#endif
#ifndef TclBN_mp_cnt_lsb
#define TclBN_mp_cnt_lsb \
	(tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */
#endif
/* Slot 64 is reserved */
/* Slot 65 is reserved */
/* Slot 66 is reserved */
/* Slot 67 is reserved */
/* Slot 68 is reserved */
/* Slot 69 is reserved */
/* Slot 70 is reserved */
/* Slot 71 is reserved */
/* Slot 72 is reserved */
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
/* Slot 76 is reserved */
/* Slot 77 is reserved */
/* Slot 78 is reserved */
/* Slot 79 is reserved */
#ifndef TclUnusedStubEntry
#define TclUnusedStubEntry \
	(tclTomMathStubsPtr->tclUnusedStubEntry) /* 80 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









806
807
808
809
810
811
812




















813
814
815
816
817
818
819
820
821
#define TclBN_mp_set_int \
	(tclTomMathStubsPtr->tclBN_mp_set_int) /* 62 */
#endif
#ifndef TclBN_mp_cnt_lsb
#define TclBN_mp_cnt_lsb \
	(tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */
#endif





















#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */

Changes to generic/tclTomMathInterface.c.

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
    mp_digit* p;

    /*
     * Allocate enough memory to hold the largest possible long
     */

    status = mp_init_size(a,
	    (CHAR_BIT * sizeof(long) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT);
    if (status != MP_OKAY) {
	Tcl_Panic("initialization failure in TclBNInitBignumFromLong");
    }

    /*
     * Convert arg to sign and magnitude.
     */







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
    mp_digit* p;

    /*
     * Allocate enough memory to hold the largest possible long
     */

    status = mp_init_size(a,
	    (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT);
    if (status != MP_OKAY) {
	Tcl_Panic("initialization failure in TclBNInitBignumFromLong");
    }

    /*
     * Convert arg to sign and magnitude.
     */
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    mp_digit *p;

    /*
     * Allocate enough memory to hold the largest possible Tcl_WideUInt.
     */

    status = mp_init_size(a,
	    (CHAR_BIT * sizeof(Tcl_WideUInt) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT);
    if (status != MP_OKAY) {
	Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt");
    }

    a->sign = MP_ZPOS;

    /*







|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    mp_digit *p;

    /*
     * Allocate enough memory to hold the largest possible Tcl_WideUInt.
     */

    status = mp_init_size(a,
	    (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT);
    if (status != MP_OKAY) {
	Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt");
    }

    a->sign = MP_ZPOS;

    /*

Changes to generic/tclUniData.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

static const unsigned short pageMap[] = {
    0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416,
    448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 736, 768, 800,
    832, 864, 896, 928, 960, 992, 224, 1024, 224, 1056, 224, 224, 1088,
    1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1344, 1344,
    1440, 1472, 1504, 1536, 1568, 1344, 1344, 1600, 1632, 1664, 1696, 1728,
    1760, 1792, 1824, 1344, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080,
    2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464,
    2496, 2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848,
    2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232,
    3264, 3296, 3328, 3360, 3392, 3296, 3424, 3456, 3488, 3520, 3552, 3584,
    3616, 3296, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 3872, 1344, 3904, 3936,
    3968, 1344, 4000, 1344, 4032, 4064, 4096, 4128, 4128, 4160, 4192, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 4224, 4256, 1344, 1344, 4288, 4320, 4352,
    4384, 4416, 1344, 4448, 4480, 4512, 4544, 1344, 4576, 4608, 4640, 4672,
    1344, 4704, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1344,
    4992, 5024, 5056, 5088, 5120, 3296, 5152, 5184, 5216, 5248, 5280, 5312,
    1344, 5344, 1344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632,
    5664, 5696, 5728, 5664, 704, 704, 224, 224, 224, 224, 5760, 224, 224,
    224, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112,
    6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496,
    6528, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6592, 6624, 4928,
    6656, 6688, 6720, 6752, 6784, 4928, 6816, 6848, 6880, 6912, 6944, 6976,
    7008, 4928, 4928, 4928, 4928, 4928, 7040, 7072, 7104, 4928, 4928, 4928,
    7136, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7168, 7200, 4928, 7232,
    7264, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6560, 6560, 6560,
    6560, 7296, 6560, 7328, 7360, 6560, 6560, 6560, 6560, 6560, 6560, 6560,
    6560, 4928, 7392, 7424, 7456, 7488, 4928, 4928, 4928, 7520, 7552, 7584,
    7616, 224, 224, 224, 7648, 7680, 7712, 1344, 7744, 7776, 7808, 7808,
    704, 7840, 7872, 7904, 3296, 7936, 4928, 4928, 7968, 4928, 4928, 4928,
    4928, 4928, 4928, 8000, 8032, 8064, 8096, 3200, 1344, 8128, 4192, 1344,
    8160, 8192, 8224, 1344, 1344, 8256, 1344, 4928, 8288, 8320, 8352, 8384,
    4928, 8352, 8416, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 4928, 4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344,

































































































































































































































































































































































    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8448, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8480, 4928, 8512, 5440, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8544, 8576, 224, 8608, 8640, 1344, 1344, 8672, 8704, 8736, 224,
    8768, 8800, 8832, 8864, 8896, 8928, 8960, 1344, 8992, 9024, 9056, 9088,
    9120, 1632, 9152, 9184, 9216, 1920, 9248, 9280, 9312, 1344, 9344, 9376,
    9408, 1344, 9440, 9472, 9504, 9536, 9568, 9600, 9632, 9664, 9664, 1344,
    9696, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 9728, 9760, 9792, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9888, 1344, 1344, 9920, 3296, 9952, 9984, 10016,
    1344, 1344, 10048, 10080, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 10112, 10144, 1344, 10176, 1344, 10208, 10240, 10272,
    10304, 10336, 10368, 1344, 1344, 1344, 10400, 10432, 64, 10464, 10496,
    10528, 4736, 10560, 10592
#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
    ,10624, 10656, 10688, 3296, 1344, 1344, 1344, 10720, 10752, 10784,
    10816, 10848, 10880, 10912, 10944, 10976, 3296, 3296, 3296, 3296, 9216,
    1344, 11008, 11040, 1344, 11072, 11104, 11136, 11168, 1344, 11200,
    3296, 11232, 11264, 11296, 1344, 11328, 11360, 11392, 11424, 1344,
    11456, 1344, 11488, 11520, 11552, 3296, 3296, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 7776, 4704, 11584, 11616, 11648, 3296,
    3296, 11680, 11712, 11744, 11776, 4736, 11808, 3296, 11840, 11872,
    11904, 3296, 3296, 1344, 11936, 11968, 6880, 12000, 12032, 12064, 12096,
    12128, 3296, 12160, 12192, 1344, 12224, 12256, 12288, 12320, 12352,
    3296, 3296, 1344, 1344, 12384, 3296, 12416, 12448, 12480, 12512, 1344,
    12544, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12576,
    1344, 12608, 3296, 12640, 12128, 12672, 12704, 12736, 12768, 12736,
    12800, 7776, 12832, 12864, 12896, 12928, 5280, 12960, 12992, 13024,
    13056, 13088, 13120, 13152, 5280, 13184, 13216, 13248, 13280, 13312,
    13344, 3296, 13376, 13408, 13440, 13472, 13504, 13536, 13568, 13600,
    3296, 3296, 3296, 3296, 1344, 13632, 13664, 13696, 1344, 13728, 13760,
    3296, 3296, 3296, 3296, 3296, 1344, 13792, 13824, 3296, 1344, 13856,
    13888, 13920, 1344, 13952, 13984, 3296, 4032, 14016, 14048, 3296, 3296,
    3296, 3296, 3296, 1344, 14080, 3296, 3296, 3296, 14112, 14144, 14176,
    14208, 14240, 14272, 3296, 3296, 14304, 14336, 14368, 14400, 14432,
    14464, 1344, 14496, 14528, 1344, 4608, 14560, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 14592, 14624, 14656, 14688, 14720, 14752, 3296, 3296,
    14784, 14816, 14848, 14880, 14912, 13984, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 14944, 14976, 15008, 15040, 3296, 3296, 15072,
    15104, 15136, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 9920, 3296, 3296, 3296, 10816,
    10816, 10816, 15168, 1344, 1344, 1344, 1344, 1344, 1344, 15200, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12736, 1344, 1344,
    15232, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 15264,
    15296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 14048, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 4608, 4736, 15328, 1344, 4736, 15360, 15392, 1344, 15424, 15456,
    15488, 15520, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    14112, 14144, 15552, 3296, 3296, 3296, 1344, 1344, 15584, 15616, 15648,
    3296, 3296, 15680, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 15712, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 4704, 3296, 12384, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 15744, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    15776, 15808, 15840, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 9792, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 1344, 1344, 1344, 15872, 15904, 15936, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 704, 15968, 16000, 4928, 4928, 4928, 16032, 3296, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 8000, 4928, 16064, 4928, 16096, 16128,
    16160, 4928, 6848, 4928, 4928, 16192, 3296, 3296, 3296, 16224, 16224,
    4928, 4928, 16256, 16288, 3296, 3296, 3296, 3296, 16320, 16352, 16384,
    16416, 16448, 16480, 16512, 16544, 16576, 16608, 16640, 16672, 16704,
    16320, 16352, 16736, 16416, 16768, 16800, 16832, 16544, 16864, 16896,
    16928, 16960, 16992, 17024, 17056, 17088, 17120, 17152, 17184, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 704, 17216, 704, 17248, 17280, 17312, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 17344, 17376, 3296,
    3296, 3296, 3296, 3296, 3296, 17408, 17440, 5664, 17472, 17504, 3296,
    3296, 3296, 1344, 17536, 17568, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 12736, 17600, 1344, 17632, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12736,
    17664, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 17696, 1344, 1344, 1344, 1344, 1344, 1344, 17728, 3296, 17760,
    17792, 17824, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 17856, 6880, 17888, 3296, 3296, 17920, 17952, 3296,
    3296, 3296, 3296, 3296, 3296, 17984, 18016, 18048, 18080, 18112, 18144,
    3296, 18176, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 4928,
    18208, 4928, 4928, 7968, 18240, 18272, 8000, 18304, 4928, 4928, 4928,
    4928, 18336, 3296, 18368, 18400, 18432, 18464, 18496, 3296, 3296, 3296,
    3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 18528, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 18560, 18592, 4928,
    4928, 4928, 18624, 4928, 4928, 18656, 18688, 18208, 4928, 18720, 4928,
    18752, 18784, 3296, 3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 7968, 18816, 18848, 18880, 18912, 18944, 4928, 4928,
    4928, 4928, 18976, 4928, 6848, 19008, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 3296, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9920, 1344, 1344, 1344, 1344, 1344, 1344, 11328,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    19040, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 19072, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 11328, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 15520
    
#endif /* TCL_UTF_MAX > 3 */
};

/*
 * The groupMap is indexed by combining the alternate page number with
 * the page offset and returns a group number that identifies a unique
 * set of character attributes.







|
|
|
|
|
|






|
|
|








|
|
|
|
|
|

















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






















































|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



















|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486


























487
488
489
490
491
492
493
494
495
496





















































497






















































498
499
500
501
502
503
504
505
506
507
508
509
510
511
512




















































































513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540















































































541























































































542
543
544
545
546
547
548

static const unsigned short pageMap[] = {
    0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416,
    448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 736, 768, 800,
    832, 864, 896, 928, 960, 992, 224, 1024, 224, 1056, 224, 224, 1088,
    1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1344, 1344,
    1440, 1472, 1504, 1536, 1568, 1344, 1344, 1600, 1632, 1664, 1696, 1728,
    1760, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112,
    2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496,
    2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880,
    2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264,
    3296, 1824, 3328, 3360, 3392, 1824, 3424, 3456, 3488, 3520, 3552, 3584,
    3616, 1824, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 3872, 1344, 3904, 3936,
    3968, 1344, 4000, 1344, 4032, 4064, 4096, 4128, 4128, 4160, 4192, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 4224, 4256, 1344, 1344, 4288, 4320, 4352,
    4384, 4416, 1344, 4448, 4480, 4512, 4544, 1344, 4576, 4608, 4640, 4672,
    1344, 4704, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1344,
    4992, 5024, 5056, 5088, 1824, 1824, 5120, 5152, 5184, 5216, 5248, 5280,
    1344, 5312, 1344, 5344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600,
    5632, 5664, 5696, 5632, 704, 5728, 224, 224, 224, 224, 5760, 224, 224,
    224, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112,
    6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496,
    6528, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6592, 6624, 4928,
    6656, 6688, 6720, 6752, 6784, 4928, 6816, 6848, 6880, 6912, 6944, 6976,
    7008, 4928, 4928, 4928, 4928, 4928, 7040, 7072, 7104, 4928, 4928, 4928,
    7136, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7168, 7200, 4928, 7232,
    7264, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6560, 6560, 6560,
    6560, 7296, 6560, 7328, 7360, 6560, 6560, 6560, 6560, 6560, 6560, 6560,
    6560, 4928, 7392, 7424, 7456, 7488, 4928, 7520, 7552, 7584, 7616, 7648,
    7680, 224, 224, 224, 7712, 7744, 7776, 1344, 7808, 7840, 7872, 7872,
    704, 7904, 7936, 7968, 1824, 8000, 4928, 4928, 8032, 4928, 4928, 4928,
    4928, 4928, 4928, 8064, 8096, 8128, 8160, 3232, 1344, 8192, 4192, 1344,
    8224, 8256, 8288, 1344, 1344, 8320, 8352, 4928, 8384, 7552, 8416, 8448,
    4928, 8416, 8480, 4928, 7552, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 4704, 4928, 4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    8512, 8544, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8576, 4928, 8608, 5408, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8640, 8672, 224, 8704, 8736, 1344, 1344, 8768, 8800, 8832, 224,
    8864, 8896, 8928, 1824, 8960, 8992, 9024, 1344, 9056, 9088, 9120, 9152,
    9184, 1632, 9216, 9248, 9280, 1952, 9312, 9344, 9376, 1344, 9408, 9440,
    9472, 1344, 9504, 9536, 9568, 9600, 9632, 9664, 9696, 9728, 9728, 1344,
    9760, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 9792, 9824, 9856, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920, 9920,
    9920, 9920, 9920, 9920, 9920, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9952, 1344, 1344, 9984, 1824, 10016, 10048,
    10080, 1344, 1344, 10112, 10144, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 10176, 10208, 1344, 10240, 1344, 10272, 10304,
    10336, 10368, 10400, 10432, 1344, 1344, 1344, 10464, 10496, 64, 10528,
    10560, 10592, 4736, 10624, 10656
#if TCL_UTF_MAX > 3
    ,10688, 10720, 10752, 1824, 1344, 1344, 1344, 8352, 10784, 10816, 10848,
    10880, 10912, 10944, 10976, 11008, 1824, 1824, 1824, 1824, 9280, 1344,
    11040, 11072, 1344, 11104, 11136, 11168, 11200, 1344, 11232, 1824,
    11264, 11296, 11328, 1344, 11360, 11392, 11424, 11456, 1344, 11488,
    1344, 11520, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 7840, 4704, 10272, 1824, 1824, 1824, 1824,
    11552, 11584, 11616, 11648, 4736, 11680, 1824, 11712, 11744, 11776,
    1824, 1824, 1344, 11808, 11840, 6880, 11872, 11904, 11936, 11968, 12000,
    1824, 12032, 12064, 1344, 12096, 12128, 12160, 12192, 12224, 1824,
    1824, 1344, 1344, 12256, 1824, 12288, 12320, 12352, 12384, 1344, 12416,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 12448, 1824,
    1824, 1824, 1824, 12000, 12480, 12512, 1824, 1824, 1824, 1824, 1824,
    12544, 12576, 12608, 12640, 5248, 12672, 12704, 12736, 12768, 12800,
    12832, 12864, 5248, 12896, 12928, 12960, 12992, 13024, 1824, 1824,
    13056, 13088, 13120, 13152, 13184, 13216, 13248, 13280, 1824, 1824,
    1824, 1824, 1344, 13312, 13344, 1824, 1344, 13376, 13408, 1824, 1824,
    1824, 1824, 1824, 1344, 13440, 13472, 1824, 1344, 13504, 13536, 13568,
    1344, 13600, 13632, 1824, 4032, 13664, 1824, 1824, 1824, 1824, 1824,
    1824, 1344, 13696, 1824, 1824, 1824, 13728, 13760, 13792, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 13824, 13856, 13888, 1344, 13920,
    13952, 1344, 4608, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    13984, 14016, 14048, 14080, 14112, 14144, 1824, 1824, 14176, 14208,
    14240, 14272, 14304, 13632, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 14336, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9984, 1824, 1824, 1824, 10848, 10848, 10848,
    14368, 1344, 1344, 1344, 1344, 1344, 1344, 14400, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 14432, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14464, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4608, 4736, 14496,
    1824, 1824, 10208, 14528, 1344, 14560, 14592, 14624, 8512, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 13728, 13760, 14656, 1824,
    1824, 1824, 1344, 1344, 14688, 14720, 14752, 1824, 1824, 14784, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14816,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14848,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 4736, 1824, 1824, 10208, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9856, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344,
    14880, 14912, 14944, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 8064, 4928, 14976,
    4928, 15008, 15040, 15072, 4928, 15104, 4928, 4928, 15136, 1824, 1824,
    1824, 1824, 15168, 4928, 4928, 15200, 15232, 1824, 1824, 1824, 1824,
    15264, 15296, 15328, 15360, 15392, 15424, 15456, 15488, 15520, 15552,
    15584, 15616, 15648, 15264, 15296, 15680, 15360, 15712, 15744, 15776,
    15488, 15808, 15840, 15872, 15904, 15936, 15968, 16000, 16032, 16064,
    16096, 16128, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 704, 16160, 704, 16192, 16224,
    16256, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 16288, 16320, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1344, 1344, 1344, 1344, 1344, 1344, 16352, 1824, 16384, 16416,
    16448, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 16480, 6880, 16512, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 16544, 16576, 16608, 16640, 16672, 16704, 1824,
    16736, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 4928, 16768,
    4928, 4928, 8032, 16800, 16832, 8064, 16864, 4928, 4928, 16768, 4928,
    16896, 1824, 16928, 16960, 16992, 17024, 17056, 1824, 1824, 1824, 1824,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 17088, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 17120, 17152, 4928, 4928,
    4928, 8032, 4928, 4928, 17184, 1824, 16768, 4928, 17216, 4928, 17248,
    17280, 1824, 1824, 16768, 7552, 4928, 17312, 4928, 17344, 16960, 4928,
    1824, 1824, 1824, 17280, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 7840, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344,


























    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,





















































    1344, 1344, 17376, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1344,






















































    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 17408,




















































































    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 17440, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344,















































































    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360























































































#endif /* TCL_UTF_MAX > 3 */
};

/*
 * The groupMap is indexed by combining the alternate page number with
 * the page offset and returns a group number that identifies a unique
 * set of character attributes.
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644
645
646



647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685


686
687
688

689
690
691
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721
722
723

724






725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792


793


794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819




820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

877
878

879
880
881
882
883
884
885
886
887
888
889
890

891
892
893
894

895
896

897
898
899






900
901
902
903
904
905
906
907
908
909

910
911

912
913
914
915
916
917


918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936



937
938







939


940
941
942



943



944










945




946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976







977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006



1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020


1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061


1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085










































































1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194


1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217


1218
1219
1220
1221
1222
1223



1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247


1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276
1277

1278
1279

1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323


1324
1325
1326


1327





1328
1329



1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357

1358

1359
1360
1361

1362

1363
1364
1365
1366

1367


1368
1369
1370

1371
1372
1373

1374
1375

1376
1377

1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464


1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478







1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499


1500
1501
1502

1503
1504
1505

1506
1507

1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518

1519
1520
1521

1522
1523
1524

1525
1526

1527
1528
1529
1530
1531

1532
1533
1534
1535

1536
1537

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550



1551
1552
1553
1554

1555
1556

1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586




1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597





1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    21, 48, 49, 50, 23, 24, 52, 53, 23, 24, 23, 24, 23, 24, 23, 24, 54,
    21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 21, 21, 21, 21, 21, 21, 55, 23, 24, 56, 57, 58, 58, 23, 24,
    59, 60, 61, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 62, 63, 64, 65,
    66, 21, 67, 67, 21, 68, 21, 69, 70, 21, 21, 21, 67, 71, 21, 72, 21,
    73, 74, 21, 75, 76, 74, 77, 78, 21, 21, 76, 21, 79, 80, 21, 21, 81,
    21, 21, 21, 21, 21, 21, 21, 82, 21, 21, 83, 21, 84, 83, 21, 21, 21,
    85, 83, 86, 87, 87, 88, 21, 21, 21, 21, 21, 89, 21, 15, 21, 21, 21,
    21, 21, 21, 21, 21, 90, 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 11, 11, 11, 11, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 92, 92, 92, 92, 92, 11, 11, 11, 11, 11, 11, 11, 92,
    11, 92, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 23, 24, 23,
    24, 92, 11, 23, 24, 0, 0, 92, 42, 42, 42, 3, 95, 0, 0, 0, 0, 11, 11,
    96, 3, 97, 97, 97, 0, 98, 0, 99, 99, 21, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 100, 101, 101, 101, 21, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 102, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 103, 104, 104, 105, 106, 107, 108, 108, 108, 109, 110, 111,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 112, 113, 114, 115, 116, 117, 7, 23, 24,
    118, 23, 24, 21, 54, 54, 54, 119, 119, 119, 119, 119, 119, 119, 119,
    119, 119, 119, 119, 119, 119, 119, 119, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 113, 113, 113, 113, 113, 113, 113, 113, 113,
    113, 113, 113, 113, 113, 113, 113, 23, 24, 14, 93, 93, 93, 93, 93,
    120, 120, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,

    24, 23, 24, 23, 24, 23, 24, 121, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 122, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 0, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,



    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    0, 0, 92, 3, 3, 3, 3, 3, 3, 21, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 21, 21, 3, 8, 0, 0, 14, 14, 4, 0, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 8, 93, 3, 93, 93, 3, 93, 93, 3, 93, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17,
    17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 3, 17, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 3, 15, 93, 93, 93, 93, 93, 93, 93, 17, 14, 93, 93, 93, 93,
    93, 93, 92, 92, 93, 93, 14, 93, 93, 93, 93, 15, 15, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 0, 17, 15, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 92, 14, 3, 3, 3, 92, 0, 0,
    93, 4, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 92, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 92, 93, 93, 93, 92, 93, 93, 93, 93, 93, 0, 0, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 93, 93, 93, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,


    15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 15, 15, 15, 15,
    15, 15, 0, 17, 17, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93,

    15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    17, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125,

    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 93, 125, 93, 15, 125, 125, 125, 93, 93, 93, 93, 93, 93,
    93, 93, 125, 125, 125, 125, 93, 125, 125, 15, 93, 93, 93, 93, 93, 93,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 3, 3, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 3, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 125, 125, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 0, 0, 0, 15, 15, 15, 15, 0, 0, 93, 15, 125, 125, 125, 93,
    93, 93, 93, 0, 0, 125, 125, 0, 0, 125, 125, 93, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 125, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 93, 93, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4,
    15, 3, 93, 0, 0, 93, 93, 125, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 0, 15, 15, 0, 15, 15, 0, 0, 93, 0, 125, 125, 125, 93, 93, 0, 0,
    0, 0, 93, 93, 0, 0, 93, 93, 93, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 93, 93, 15, 15, 15, 93, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93,

    125, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15,
    15, 15, 0, 0, 93, 15, 125, 125, 125, 93, 93, 93, 93, 93, 0, 93, 93,
    125, 0, 125, 125, 93, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4,
    0, 0, 0, 0, 0, 0, 0, 15, 93, 93, 93, 93, 93, 93, 0, 93, 125, 125, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15,

    0, 0, 93, 15, 125, 93, 125, 93, 93, 93, 93, 0, 0, 125, 125, 0, 0, 125,






    125, 93, 0, 0, 0, 0, 0, 0, 0, 93, 93, 125, 0, 0, 0, 0, 15, 15, 0, 15,
    15, 15, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 15, 0, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15,
    0, 15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 125, 125, 93,
    125, 125, 0, 0, 0, 125, 125, 125, 0, 125, 125, 125, 93, 0, 0, 15, 0,
    0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14,
    0, 0, 0, 0, 0, 93, 125, 125, 125, 93, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 93, 15, 93, 93, 93, 125,
    125, 125, 125, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0,
    0, 93, 93, 0, 15, 15, 15, 0, 0, 15, 0, 0, 15, 15, 93, 93, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 3, 18, 18, 18, 18,
    18, 18, 18, 14, 15, 93, 125, 125, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 93, 15, 125, 93, 125,
    125, 125, 125, 125, 0, 93, 125, 125, 0, 125, 125, 93, 93, 0, 0, 0,
    0, 0, 0, 0, 125, 125, 0, 0, 0, 0, 0, 0, 15, 15, 0, 15, 15, 93, 93,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 125, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 93, 93, 125, 125, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 15, 125,
    125, 125, 93, 93, 93, 93, 0, 125, 125, 125, 0, 125, 125, 125, 93, 15,
    14, 0, 0, 0, 0, 15, 15, 15, 125, 18, 18, 18, 18, 18, 18, 18, 15, 15,
    15, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 14, 15, 15, 15, 15, 15, 15, 0, 93, 125, 125, 0, 15,

    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 93, 0, 0,
    0, 0, 125, 125, 125, 93, 93, 93, 0, 93, 0, 125, 125, 125, 125, 125,

    125, 125, 125, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    125, 125, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 15, 15, 93, 93, 93, 93, 93,
    93, 93, 0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 92, 93, 93, 93, 93,
    93, 93, 93, 93, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 93, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 15, 0,
    0, 15, 15, 15, 15, 15, 0, 92, 0, 93, 93, 93, 93, 93, 93, 93, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15, 15, 15, 15, 15, 14, 14, 14, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 3, 14, 14, 14, 93, 93,
    14, 14, 14, 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 14, 93, 14, 93, 14, 93, 5, 6, 5, 6, 125, 125,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125, 93, 93, 93, 93, 93,
    3, 93, 93, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 0, 14, 14, 14, 14, 14, 14, 14, 14, 93, 14, 14,
    14, 14, 14, 14, 0, 14, 14, 3, 3, 3, 3, 3, 14, 14, 14, 14, 3, 3, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 93,
    93, 93, 93, 125, 93, 93, 93, 93, 93, 93, 125, 93, 93, 125, 125, 93,
    93, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 15, 15, 15,
    15, 15, 15, 125, 125, 93, 93, 15, 15, 15, 15, 93, 93, 93, 15, 125,
    125, 125, 15, 15, 125, 125, 125, 125, 125, 125, 125, 15, 15, 15, 93,
    93, 93, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93,


    125, 125, 93, 93, 125, 125, 125, 125, 125, 125, 93, 15, 125, 9, 9,


    9, 9, 9, 9, 9, 9, 9, 9, 125, 125, 125, 93, 14, 14, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 0, 126, 0, 0, 0, 0, 0, 126, 0, 0, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    3, 92, 127, 127, 127, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 93, 93, 93, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 105, 105, 105, 105, 105, 105, 0, 0, 111, 111, 111, 111, 111,




    111, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 3, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 3, 3, 3, 129, 129, 129, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 125, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 93, 125, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 93, 93, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 125, 93, 93, 93, 93, 93, 93,
    93, 125, 125, 125, 125, 125, 125, 125, 125, 93, 125, 125, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 3, 3, 3, 92, 3, 3, 3, 4, 15, 93, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3,
    3, 3, 93, 93, 93, 17, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    93, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 93, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    93, 93, 93, 125, 125, 125, 125, 93, 93, 125, 125, 125, 0, 0, 0, 0,
    125, 125, 93, 125, 125, 125, 125, 125, 125, 93, 93, 93, 0, 0, 0, 0,
    14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 125, 125, 93, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 93, 125, 93, 93,
    93, 93, 93, 93, 93, 0, 93, 125, 93, 125, 125, 93, 93, 93, 93, 93, 93,
    93, 93, 125, 125, 125, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 0, 0, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 92,
    3, 3, 3, 3, 3, 3, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 120, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
    93, 93, 93, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 125, 93, 93, 93, 93, 93, 125, 93, 125, 125, 125, 125, 125, 93,

    125, 125, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 14, 14, 14, 14,

    14, 93, 93, 93, 93, 93, 93, 93, 93, 93, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 3, 3, 0, 93, 93, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 125, 93, 93, 93, 93, 125, 125, 93, 93, 125, 93, 93, 93,
    15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 125, 93, 93, 125, 125, 125, 93, 125, 93, 93, 93,
    125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 125,
    125, 125, 125, 125, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    125, 125, 93, 93, 0, 0, 0, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 3, 3, 130,

    131, 132, 133, 133, 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, 0, 138, 138,
    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 0,

    0, 138, 138, 138, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 93,
    93, 93, 3, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125,

    93, 93, 93, 93, 93, 93, 93, 15, 15, 15, 15, 93, 15, 15, 15, 15, 15,
    15, 93, 15, 15, 125, 93, 93, 15, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,






    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 92, 139, 21, 21,
    21, 140, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 141, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 92, 92, 92,
    92, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, 142, 21, 21, 143, 21,

    144, 144, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145,
    145, 145, 144, 144, 144, 144, 144, 144, 0, 0, 145, 145, 145, 145, 145,

    145, 0, 0, 144, 144, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145,
    145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 145, 145,
    145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 0, 0, 145,
    145, 145, 145, 145, 145, 0, 0, 21, 144, 21, 144, 21, 144, 21, 144,
    0, 145, 0, 145, 0, 145, 0, 145, 144, 144, 144, 144, 144, 144, 144,
    144, 145, 145, 145, 145, 145, 145, 145, 145, 146, 146, 147, 147, 147,


    147, 148, 148, 149, 149, 150, 150, 151, 151, 0, 0, 144, 144, 144, 144,
    144, 144, 144, 144, 152, 152, 152, 152, 152, 152, 152, 152, 144, 144,
    144, 144, 144, 144, 144, 144, 152, 152, 152, 152, 152, 152, 152, 152,
    144, 144, 144, 144, 144, 144, 144, 144, 152, 152, 152, 152, 152, 152,
    152, 152, 144, 144, 21, 153, 21, 0, 21, 21, 145, 145, 154, 154, 155,
    11, 156, 11, 11, 11, 21, 153, 21, 0, 21, 21, 157, 157, 157, 157, 155,
    11, 11, 11, 144, 144, 21, 21, 0, 0, 21, 21, 145, 145, 158, 158, 0,
    11, 11, 11, 144, 144, 21, 21, 21, 114, 21, 21, 145, 145, 159, 159,
    118, 11, 11, 11, 0, 0, 21, 153, 21, 0, 21, 21, 160, 160, 161, 161,
    155, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17,
    8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20, 5, 16, 3, 3, 3, 3, 3,
    3, 3, 3, 162, 163, 17, 17, 17, 17, 17, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, 6, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 17, 17, 17,
    17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 92, 0, 0, 18,
    18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 92, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 7, 7, 7, 5, 6, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0,



    0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 120, 120, 120, 120, 93, 120, 120, 120, 93, 93, 93, 93,







    93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


    0, 0, 0, 14, 14, 108, 14, 14, 14, 14, 108, 14, 14, 21, 108, 108, 108,
    21, 21, 108, 108, 108, 21, 14, 108, 14, 14, 7, 108, 108, 108, 108,
    108, 14, 14, 14, 14, 14, 14, 108, 14, 164, 14, 108, 14, 165, 166, 108,



    108, 14, 21, 108, 108, 167, 108, 21, 15, 15, 15, 15, 21, 14, 14, 21,



    21, 108, 108, 7, 7, 7, 7, 7, 108, 21, 21, 21, 21, 14, 7, 14, 14, 168,










    14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,




    169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,

    169, 169, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
    170, 170, 170, 170, 129, 129, 129, 23, 24, 129, 129, 129, 129, 18,
    14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14,
    14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7,
    14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14,
    14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14,
    14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,







    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 171, 171, 171, 171, 171, 171,
    171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
    171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 172, 172, 172,
    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172,
    172, 172, 172, 172, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7,
    7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
    5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5,
    6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,



    14, 14, 14, 14, 14, 14, 14, 14, 14, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 23, 24, 173, 174, 175, 176, 177, 23, 24, 23,
    24, 23, 24, 178, 179, 180, 181, 21, 23, 24, 21, 23, 24, 21, 21, 21,
    21, 21, 92, 92, 182, 182, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14, 14,
    23, 24, 23, 24, 93, 93, 93, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3, 18,
    3, 3, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183,
    183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183,
    183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 0, 183, 0, 0,


    0, 0, 0, 183, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20, 3, 16, 20,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3, 16, 20, 5,
    6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    14, 14, 3, 3, 3, 5, 6, 5, 6, 5, 6, 5, 6, 8, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 2, 3, 3, 3, 14, 92, 15,
    129, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6,
    8, 5, 6, 6, 14, 129, 129, 129, 129, 129, 129, 129, 129, 129, 93, 93,
    93, 93, 125, 125, 8, 92, 92, 92, 92, 92, 14, 14, 129, 129, 129, 92,
    15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 93, 93, 11, 11, 92, 92,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 92, 92, 92, 15, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14, 18, 18, 18, 18, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 14, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92,


    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 3,
    3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 15, 93, 120, 120, 120, 3, 93, 93, 93, 93, 93, 93, 93,

    93, 93, 93, 3, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 92,
    92, 93, 93, 15, 15, 15, 15, 15, 15, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 93, 93, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 11,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 92, 92, 92, 92, 92, 92, 92, 92, 92, 11, 11, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 92, 21, 21, 21, 21, 21,
    21, 21, 21, 23, 24, 23, 24, 184, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 92, 11, 11, 23, 24, 185, 21, 15, 23, 24, 23, 24, 186, 21, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 187, 188, 189, 190, 187, 21, 191, 192, 193, 194, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 195, 196, 197, 23,
    24, 23, 24, 0, 0, 0, 0, 0, 23, 24, 0, 21, 0, 21, 23, 24, 23, 24, 0,










































































    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    92, 92, 92, 23, 24, 15, 92, 92, 21, 15, 15, 15, 15, 15, 15, 15, 93,
    15, 15, 15, 93, 15, 15, 15, 15, 93, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125,
    93, 93, 125, 14, 14, 14, 14, 93, 0, 0, 0, 18, 18, 18, 18, 18, 18, 14,
    14, 4, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 125, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 15, 15, 15, 15, 15, 15,
    3, 3, 3, 15, 3, 15, 15, 93, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93,
    93, 93, 93, 93, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 125,
    125, 93, 93, 93, 93, 125, 125, 93, 93, 125, 125, 125, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 0, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 3, 3, 15, 15, 15, 15, 15, 93, 92, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 125, 125, 93, 93,
    125, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 93, 15, 15,
    15, 15, 15, 15, 15, 15, 93, 125, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 125, 93, 125,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 93, 15, 93, 93, 93, 15, 15, 93, 93, 15, 15, 15, 15, 15, 93, 93,
    15, 93, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 92, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 125, 93, 93, 125, 125, 3, 3, 15, 92, 92, 125, 93, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 198, 21,
    21, 21, 21, 21, 21, 21, 11, 92, 92, 92, 92, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 92, 11, 11, 0, 0, 0, 0, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 15,
    15, 15, 125, 125, 93, 125, 125, 93, 125, 125, 3, 125, 93, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
    200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
    200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
    201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
    201, 201, 201, 201, 201, 201, 201, 201, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 15, 93, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 0, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 5, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4, 14, 14, 14, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 3, 3, 3, 3, 3,
    3, 3, 5, 6, 3, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 3, 8, 8, 12, 12, 5, 6, 5, 6, 5, 6, 5, 6,
    5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 5, 6, 3, 3, 3, 3, 12, 12, 12, 3, 3, 3,
    0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7, 8, 7, 7, 7, 0, 3, 4,
    3, 3, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 17,
    0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    5, 7, 6, 7, 5, 6, 3, 5, 6, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 15,
    15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 14,
    7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, 14,
    0, 0
#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
    ,15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 129, 129,


    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 18, 18, 18, 18, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18,
    14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 93, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 129, 15, 15, 15, 15, 15, 15, 15, 15, 129, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 15, 15, 15, 15,

    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 129, 129, 129, 129,


    129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,



    203, 203, 203, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 0, 0, 0, 0, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 204, 204, 204,
    204, 204, 204, 204, 204, 204, 204, 204, 0, 204, 204, 204, 204, 204,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 0, 204, 204, 204,
    204, 204, 204, 204, 0, 204, 204, 0, 205, 205, 205, 205, 205, 205, 205,
    205, 205, 205, 205, 0, 205, 205, 205, 205, 205, 205, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 0, 205, 205, 205, 205, 205, 205, 205,
    0, 205, 205, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92,
    92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,


    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    15, 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18, 18, 18, 18, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0,
    0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18,
    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 18, 18, 15, 15, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 15, 93, 93, 93, 0, 93, 93, 0, 0, 0, 0, 0, 93,
    93, 93, 93, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 93, 93, 93, 0, 0, 0, 0, 93, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18,

    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 93, 0, 0, 0, 0, 18, 18, 18, 18, 18, 3, 3, 3,
    3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,

    3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18,

    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 98, 98,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 0, 0, 0,
    0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 93, 93, 93, 93,
    0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0,
    0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 93, 93, 8, 0, 0, 15, 15, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93,
    18, 18, 18, 18, 18, 18, 18, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 18, 18, 18, 18,
    3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 93, 93, 93, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 18, 18,
    18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 125, 93, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 93, 15, 15, 93, 93, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 125, 125, 93, 93, 3, 3,
    17, 3, 3, 3, 3, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 0, 0, 0, 0, 0, 0, 93, 93, 93, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 125,


    93, 93, 93, 93, 93, 93, 93, 93, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3,
    3, 3, 3, 15, 125, 125, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,


    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 3, 3, 15,





    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93,



    93, 93, 93, 93, 93, 125, 125, 15, 15, 15, 15, 3, 3, 3, 3, 93, 93, 93,
    93, 3, 125, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 3, 15, 3, 3, 3, 0,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 125, 125, 93, 125, 93, 93,
    3, 3, 3, 3, 3, 3, 93, 15, 15, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 93,
    93, 125, 125, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15,
    15, 15, 15, 15, 0, 93, 93, 15, 125, 125, 93, 125, 125, 125, 125, 0,
    0, 125, 125, 0, 0, 125, 125, 125, 0, 0, 15, 0, 0, 0, 0, 0, 0, 125,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 125, 125, 0, 0, 93, 93, 93, 93,
    93, 93, 93, 0, 0, 0, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    125, 125, 93, 93, 93, 125, 93, 15, 15, 15, 15, 3, 3, 3, 3, 3, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 3, 93, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    125, 125, 125, 93, 93, 93, 93, 93, 93, 125, 93, 125, 125, 125, 125,
    93, 93, 125, 93, 93, 15, 15, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,

    15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 0, 0,

    125, 125, 125, 125, 93, 93, 125, 93, 93, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 93, 93, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 125, 125, 93, 125, 93,

    93, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9,


    9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 125, 93, 125, 125, 93, 93, 93,

    93, 93, 93, 125, 93, 15, 3, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 125, 125, 93, 93, 93, 93, 125, 93, 93, 93, 93, 93, 0, 0, 0, 0,

    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 3, 3, 3, 14, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125,
    125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125, 93, 93, 3, 0, 0,

    0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 125, 125, 125, 125, 125, 125, 0, 125, 125, 0, 0, 93, 93, 125, 93,
    15, 125, 15, 125, 93, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 0, 0, 93,
    93, 125, 125, 125, 125, 93, 15, 3, 15, 125, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93,
    93, 93, 93, 125, 15, 93, 93, 93, 93, 3, 3, 3, 3, 3, 3, 3, 3, 93, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 93, 93, 93, 93, 93, 93, 125, 125, 93, 93,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125, 93, 93, 3, 3, 3, 15,
    3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 93, 93,
    93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 125, 93, 15, 3, 3, 3,
    3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 0, 125, 93, 93, 93, 93, 93, 93, 93, 125,
    93, 93, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 0, 0, 0,
    93, 0, 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 15, 93, 0, 0, 0, 0, 0,
    0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 125, 125, 125, 125, 125, 0, 93, 93, 0, 125, 125, 93,
    125, 93, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 125, 125, 3, 3, 0,
    0, 0, 0, 0, 0, 0, 93, 93, 15, 125, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 125, 125, 93, 93, 93, 93, 93, 0, 0, 0, 125,
    125, 93, 125, 93, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 4, 4, 4, 4, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 93, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 93, 93, 93, 93, 93, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 93, 93, 93, 93, 3, 3, 3, 3, 3, 14, 14, 14, 14, 92, 92,
    92, 92, 3, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 0, 18, 18, 18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 3, 3, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 93, 15, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93,
    93, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3,
    92, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 125, 0, 0, 0, 0, 0, 0,


    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92,
    92, 0, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 0, 15, 15, 15, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,

    15, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 93, 93, 3, 17,
    17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,







    93, 93, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 125, 125, 93, 93, 93, 14,
    14, 14, 125, 125, 125, 125, 125, 125, 17, 17, 17, 17, 17, 17, 17, 17,
    93, 93, 93, 93, 93, 93, 93, 93, 14, 14, 93, 93, 93, 93, 93, 93, 93,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 93, 93, 93, 93,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 93, 93, 93, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21,


    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108,

    0, 108, 108, 0, 0, 108, 0, 0, 108, 108, 0, 0, 108, 108, 108, 108, 0,
    108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 0, 21, 0, 21,
    21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 0, 108, 108, 108, 108, 0,
    0, 108, 108, 108, 108, 108, 108, 108, 108, 0, 108, 108, 108, 108, 108,

    108, 108, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 0, 108, 108,
    108, 108, 0, 108, 108, 108, 108, 108, 0, 108, 0, 0, 0, 108, 108, 108,

    108, 108, 108, 108, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,

    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21, 21, 0, 0, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,

    21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,

    108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7,
    21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21,
    21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 7, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,



    21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 21, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,

    93, 93, 93, 93, 93, 14, 14, 14, 14, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 14, 14, 14, 14, 14, 14, 14,

    14, 93, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 93,
    14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0,
    0, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 93, 93, 93,
    93, 93, 93, 93, 0, 93, 93, 0, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 93, 93, 93, 93,
    93, 93, 93, 92, 92, 92, 92, 92, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 15, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 93, 93, 93, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 93, 93, 93, 93,
    93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,




    207, 207, 207, 207, 207, 207, 93, 93, 93, 93, 93, 93, 93, 92, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 14, 18, 18, 18, 4, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 0,





    0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0,
    15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15,
    0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0,
    0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    
#endif /* TCL_UTF_MAX > 3 */
};

/*
 * Each group represents a unique set of character attributes.  The attributes
 * are encoded into a 32-bit value as follows:
 *







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|



|
|
|
>
|
<

|
>
>
>


<
<
<
|
|
|
|



|
|

|
|
|
|

|
|

|

|
|

|



|
|
|
|


|
>
>
|
|
|
>
|
<
<
<
>



|
<
|
|
<
|
<
<
<
<
<
|


<
|
|
|
>
|
|
|
|
|
|
|
|


>
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
>

<
|
|
<
>
|
|


|
|
|
<
|
|
|
<
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|


<
<
<
<
|
|
|
|
|
|
|
|
|


|
|
|
|
<
<
<
<
>
>
>
>
|

|
|

|
|
|
|
|
|

|
|

|
|
|


|
|



|

|




|
|










|
|
|
|
|
|
|
<
<
|


<
>
|
|
>
|
|
|
<
|
|
|
|
|
|
|
|
>
|
<
|
|
>
|
<
>
|
|

>
>
>
>
>
>

<
|

|
<
<
<
|
|
>
|
|
>
|
<
|
|
<
|
>
>
|
|
|
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
>
>
>
>
>
>
>
|
>
>
|
|
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>

>
|
|
<
|

<
|
|
<
<
<
<
<


<
<
|
|
|
<
<
<
<
<
<
|

<
|
>
>
>
>
>
>
>
<
<
<
<
<
<
|
|
|

|
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<


<
|
>
>
>
|


|
<
<
<
<
|
|
|
|
<
<
>
>
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|

|
|
|
|
|
|

|
|
|
|
|
>
>

|
|
|
|
|
|
|
<
>
|
|
|
|

|
|
|
|
|
|
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|

|
|
|

|
|

|
|
|
|
|
|





|
<
<


|
>
>
|
|
<
<
|
|
|

|

|
|
|

|
|
|
|
<
<
<
|
>
|
>
>
|
<
<
<
|
|
>
>
>
|

|
|
<
<
<
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
|
|
>
>
|
|
|
>
|
|
|
|
|
|
|
|
|
|

|
|
|
|
<
<
<
<
<
|
|
>
|

<
|
|
>
|
|
>
|
|
|
<
|
|
<
<
<
<
<
<
<
<
|
|
|
<
|
|
|
|
|
<
|
>
|
|
|
|
<
<
<
<
|

|
|
<
<
|
|
|

|
>
>
|
|
|
>
>
|
>
>
>
>
>
|
|
>
>
>
|
|
|
|
|
|
<
|
<
|
|
|


<
<
<
<
<
<
<
<
<
<
|
<
|
<
>

>
|
|
|
>
|
>
|
|
|
<
>
|
>
>
|
|
|
>
|
|
|
>
|
|
>
|
<
>
|
|
|
|
|
<
<
<
<
|
<
<
|
<
<
<
<

|
|
<
|
<
|
|
|
|

|
|
|



|
|
|


|
|



|
|
|
<
<
<
<
<
<
|
<
<
<
<
|
|
|
|
|
<
<
|
|
|
|
|
<
<
|
|
|
|
<
<

|
<
<
<
<
<
<
|
>
>
|
<
|
<
|
|
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
|
<
<
<
|
<
<
<
<
<
<
<
<
|
|
|
|
|
|
<
<
>
>
|
|
<
>
|
|
<
>
|
|
>
|
|
<
<
<
<
|
<
>
|
|
<
>
|
|
<
>
|

|
>
|
|
>
|
<
<

|
>
|
<
<
|
>
|
<
>
|
|
|
|
|
|
|
|

|
|
|
|
>
>
>
|
|
|
<
>
|
<
>
|
|
<
|
<
<
<
<
<
<
<

|
<
<
|
|
<
|
<
<
<
<
<
|
|
<
<
<
<
>
>
>
>
|
|
|
|
|
<
<
<
<
|
|
>
>
>
>
>
<
<
<
<
<
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|

<
<
<
<
<
<

|
|
|
<
|
|
|
|
|
|
<

|
|
|
<

|
<
|
|
|
<
|
>
|
|
|
|
<







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662



663
664
665
666
667

668
669

670





671
672
673

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

729
730

731
732
733
734
735
736
737
738

739
740
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769




770
771
772
773
774
775
776
777
778
779
780
781
782
783
784




785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839


840
841
842

843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858
859

860
861
862
863

864
865
866
867
868
869
870
871
872
873
874

875
876
877



878
879
880
881
882
883
884

885
886

887
888
889
890
891
892



893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

951
952

953
954





955
956


957
958
959






960
961

962
963
964
965
966
967
968
969






970
971
972
973
974

975
976


977









978
979

980
981
982
983
984
985
986
987




988
989
990
991


992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134




1135


































1136






































1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161


1162
1163
1164
1165
1166
1167
1168


1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182



1183
1184
1185
1186
1187
1188



1189
1190
1191
1192
1193
1194
1195
1196
1197



1198
1199
1200
1201
1202










1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225





1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238
1239

1240
1241








1242
1243
1244

1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255




1256
1257
1258
1259


1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

1289

1290
1291
1292
1293
1294










1295

1296

1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

1325
1326
1327
1328
1329
1330




1331


1332




1333
1334
1335

1336

1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360






1361




1362
1363
1364
1365
1366


1367
1368
1369
1370
1371


1372
1373
1374
1375


1376
1377






1378
1379
1380
1381

1382

1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401



1402








1403
1404
1405
1406
1407
1408


1409
1410
1411
1412

1413
1414
1415

1416
1417
1418
1419
1420
1421




1422

1423
1424
1425

1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437


1438
1439
1440
1441


1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466

1467
1468
1469

1470







1471
1472


1473
1474

1475





1476
1477




1478
1479
1480
1481
1482
1483
1484
1485
1486




1487
1488
1489
1490
1491
1492
1493





1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511






1512
1513
1514
1515

1516
1517
1518
1519
1520
1521

1522
1523
1524
1525

1526
1527

1528
1529
1530

1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    21, 48, 49, 50, 23, 24, 52, 53, 23, 24, 23, 24, 23, 24, 23, 24, 54,
    21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 21, 21, 21, 21, 21, 21, 55, 23, 24, 56, 57, 58, 58, 23, 24,
    59, 60, 61, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 62, 63, 64, 65,
    66, 21, 67, 67, 21, 68, 21, 69, 70, 21, 21, 21, 67, 71, 21, 72, 21,
    73, 74, 21, 75, 76, 74, 77, 78, 21, 21, 76, 21, 79, 80, 21, 21, 81,
    21, 21, 21, 21, 21, 21, 21, 82, 21, 21, 83, 21, 21, 83, 21, 21, 21,
    84, 83, 85, 86, 86, 87, 21, 21, 21, 21, 21, 88, 21, 15, 21, 21, 21,
    21, 21, 21, 21, 21, 89, 90, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 11, 11, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 91, 91, 91, 91, 91, 11, 11, 11, 11, 11, 11, 11, 91,
    11, 91, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 93, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 23, 24, 23,
    24, 91, 11, 23, 24, 0, 0, 91, 42, 42, 42, 3, 94, 0, 0, 0, 0, 11, 11,
    95, 3, 96, 96, 96, 0, 97, 0, 98, 98, 21, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 99, 100, 100, 100, 21, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 101, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 102, 103, 103, 104, 105, 106, 107, 107, 107, 108, 109, 110,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 111, 112, 113, 114, 115, 116, 7, 23, 24,
    117, 23, 24, 21, 54, 54, 54, 118, 118, 118, 118, 118, 118, 118, 118,
    118, 118, 118, 118, 118, 118, 118, 118, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 112, 112, 112, 112, 112, 112, 112, 112, 112,
    112, 112, 112, 112, 112, 112, 112, 23, 24, 14, 92, 92, 92, 92, 92,
    119, 119, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 120, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 121, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,

    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
    0, 0, 91, 3, 3, 3, 3, 3, 3, 21, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,



    123, 123, 123, 21, 21, 3, 8, 0, 0, 14, 14, 4, 0, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 8, 92, 3, 92, 92, 3, 92, 92, 3, 92, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17,
    17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 3, 17, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15,
    92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 3, 15, 92, 92, 92, 92, 92, 92, 92, 17, 14, 92, 92, 92, 92,
    92, 92, 91, 91, 92, 92, 14, 92, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 0, 17, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 14, 3, 3, 3, 91, 0, 0,
    92, 4, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 91, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 91, 92, 92, 92, 91, 92, 92, 92, 92, 92, 0, 0, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 92, 92, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 17,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,



    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 92, 124, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92,

    92, 124, 124, 124, 124, 92, 124, 124, 15, 92, 92, 92, 92, 92, 92, 92,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 3, 3, 9, 9, 9, 9, 9,

    9, 9, 9, 9, 9, 3, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,





    15, 15, 15, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15,

    0, 0, 0, 15, 15, 15, 15, 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92,
    0, 0, 124, 124, 0, 0, 124, 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 124,
    0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4, 15, 3, 92,
    0, 0, 92, 92, 124, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0,
    15, 15, 0, 15, 15, 0, 0, 92, 0, 124, 124, 124, 92, 92, 0, 0, 0, 0,
    92, 92, 0, 0, 92, 92, 92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92,
    92, 15, 15, 15, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 124, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15,
    0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 0, 92, 92, 124, 0,
    124, 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4, 0, 0, 0,
    0, 0, 0, 0, 15, 92, 92, 92, 92, 92, 92, 0, 92, 124, 124, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0,
    92, 15, 124, 92, 124, 92, 92, 92, 92, 0, 0, 124, 124, 0, 0, 124, 124,
    92, 0, 0, 0, 0, 0, 0, 0, 0, 92, 124, 0, 0, 0, 0, 15, 15, 0, 15, 15,
    15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18, 18,
    18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 0, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15, 0,
    15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 124, 124, 92, 124,
    124, 0, 0, 0, 124, 124, 124, 0, 124, 124, 124, 92, 0, 0, 15, 0, 0,
    0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14, 0,
    0, 0, 0, 0, 92, 124, 124, 124, 92, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 92, 92, 92, 124,
    124, 124, 124, 0, 92, 92, 92, 0, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0,
    0, 92, 92, 0, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 92, 92, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18,
    18, 18, 14, 15, 92, 124, 124, 3, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, 124, 92, 124,
    124, 124, 124, 124, 0, 92, 124, 124, 0, 124, 124, 92, 92, 0, 0, 0,
    0, 0, 0, 0, 124, 124, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 15, 92, 92, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 92, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 15, 124, 124, 124,
    92, 92, 92, 92, 0, 124, 124, 124, 0, 124, 124, 124, 92, 15, 14, 0,
    0, 0, 0, 15, 15, 15, 124, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 92,
    92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 14, 15, 15, 15, 15, 15, 15, 0, 0, 124, 124, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 92, 0, 0, 0, 0, 124,

    124, 124, 92, 92, 92, 0, 92, 0, 124, 124, 124, 124, 124, 124, 124,
    124, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 124, 124,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 92, 92, 92, 92, 92, 92, 92,
    0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 91, 92, 92, 92, 92, 92, 92,
    92, 92, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, 0, 15, 15,

    0, 15, 0, 0, 15, 15, 0, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 0, 15, 0,
    0, 15, 15, 0, 15, 15, 15, 15, 92, 15, 15, 92, 92, 92, 92, 92, 92, 0,

    92, 92, 15, 0, 0, 15, 15, 15, 15, 15, 0, 91, 0, 92, 92, 92, 92, 92,
    92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15, 15, 15, 15, 15, 14,
    14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 3, 14, 14,
    14, 92, 92, 14, 14, 14, 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 92, 14, 92, 14, 92, 5, 6, 5,
    6, 124, 124, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92,
    92, 92, 92, 3, 92, 92, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    92, 14, 14, 14, 14, 14, 14, 0, 14, 14, 3, 3, 3, 3, 3, 14, 14, 14, 14,
    3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124,
    124, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 124, 92, 92, 124,
    124, 92, 92, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 15,
    15, 15, 15, 15, 15, 124, 124, 92, 92, 15, 15, 15, 15, 92, 92, 92, 15,
    124, 124, 124, 15, 15, 124, 124, 124, 124, 124, 124, 124, 15, 15, 15,
    92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 124, 124, 92, 92, 124, 124, 124, 124, 124, 124, 92, 15, 124, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 124, 124, 124, 92, 14, 14, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 0, 125, 0, 0, 0, 0, 0, 125, 0, 0,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,




    126, 3, 91, 126, 126, 126, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15,
    15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 127, 127, 127,




    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 104, 104, 104, 104, 104, 104, 0, 0, 110, 110, 110, 110,
    110, 110, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 128, 128, 128, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 92, 92, 92, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 92, 92, 92, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 92, 92, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 92, 92, 92, 92, 92, 92,
    92, 124, 124, 124, 124, 124, 124, 124, 124, 92, 124, 124, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 91, 3, 3, 3, 4, 15, 92, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3,
    3, 3, 92, 92, 92, 17, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 92, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    92, 92, 92, 124, 124, 124, 124, 92, 92, 124, 124, 124, 0, 0, 0, 0,
    124, 124, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 0, 0, 0, 0,
    14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 92, 124, 124, 92, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 124, 92, 92,
    92, 92, 92, 92, 92, 0, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92,
    92, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 0, 0, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 91,
    3, 3, 3, 3, 3, 3, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,


    92, 92, 92, 119, 0, 92, 92, 92, 92, 124, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 92, 92, 92, 124, 92, 124,
    124, 124, 124, 124, 92, 124, 124, 15, 15, 15, 15, 15, 15, 15, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 92, 92, 124, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92, 92, 124, 124,

    92, 92, 124, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 124, 124,
    124, 92, 124, 92, 92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3,
    3, 15, 15, 15, 15, 124, 124, 124, 124, 124, 124, 124, 124, 92, 92,
    92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 0, 0, 0, 3, 3, 3, 3, 3, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 91,
    91, 91, 91, 91, 3, 3, 129, 130, 131, 132, 132, 133, 134, 135, 136,
    0, 0, 0, 0, 0, 0, 0, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,

    137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
    137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
    137, 137, 137, 137, 137, 0, 0, 137, 137, 137, 3, 3, 3, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 3, 92, 92, 92, 92, 92, 92, 92,

    92, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15,
    15, 92, 15, 15, 15, 15, 124, 124, 92, 15, 15, 124, 92, 92, 0, 0, 0,
    0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 91, 138, 21, 21, 21, 139, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,

    21, 21, 21, 21, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 0, 92, 92, 92, 92, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,



    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21,
    140, 21, 21, 141, 21, 142, 142, 142, 142, 142, 142, 142, 142, 143,
    143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 0,
    0, 143, 143, 143, 143, 143, 143, 0, 0, 142, 142, 142, 142, 142, 142,
    142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142,
    142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142,
    142, 142, 142, 142, 0, 0, 143, 143, 143, 143, 143, 143, 0, 0, 21, 142,

    21, 142, 21, 142, 21, 142, 0, 143, 0, 143, 0, 143, 0, 143, 142, 142,
    142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143,

    144, 144, 145, 145, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149,
    0, 0, 142, 142, 142, 142, 142, 142, 142, 142, 150, 150, 150, 150, 150,
    150, 150, 150, 142, 142, 142, 142, 142, 142, 142, 142, 150, 150, 150,
    150, 150, 150, 150, 150, 142, 142, 142, 142, 142, 142, 142, 142, 150,
    150, 150, 150, 150, 150, 150, 150, 142, 142, 21, 151, 21, 0, 21, 21,
    143, 143, 152, 152, 153, 11, 154, 11, 11, 11, 21, 151, 21, 0, 21, 21,



    155, 155, 155, 155, 153, 11, 11, 11, 142, 142, 21, 21, 0, 0, 21, 21,
    143, 143, 156, 156, 0, 11, 11, 11, 142, 142, 21, 21, 21, 113, 21, 21,
    143, 143, 157, 157, 117, 11, 11, 11, 0, 0, 21, 151, 21, 0, 21, 21,
    158, 158, 159, 159, 153, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    17, 17, 17, 17, 17, 8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20,
    5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 160, 161, 17, 17, 17, 17, 17, 2, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5,
    6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 2, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 18, 91, 0, 0, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 91, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 0, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 119, 119, 119, 119, 92, 119, 119,
    119, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 107, 14, 14, 14, 14, 107, 14,
    14, 21, 107, 107, 107, 21, 21, 107, 107, 107, 21, 14, 107, 14, 14,
    7, 107, 107, 107, 107, 107, 14, 14, 14, 14, 14, 14, 107, 14, 162, 14,
    107, 14, 163, 164, 107, 107, 14, 21, 107, 107, 165, 107, 21, 15, 15,
    15, 15, 21, 14, 14, 21, 21, 107, 107, 7, 7, 7, 7, 7, 107, 21, 21, 21,
    21, 14, 7, 14, 14, 166, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 167, 167, 167, 167, 167, 167, 167, 167, 167,
    167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 168, 168, 168,
    168, 168, 168, 168, 168, 168, 168, 168, 168, 128, 128, 128, 23, 24,
    128, 128, 128, 128, 18, 14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14,
    14, 14, 14, 7, 7, 14, 14, 14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14,
    14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 7, 7, 14, 14, 7, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
    169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170,
    170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
    170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 18, 18, 18, 18, 18,

    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,

    14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,





    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,


    14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6,






    5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,

    18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7,
    7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5,
    6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14,






    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7,
    7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,

    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,


    14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,









    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,

    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 122, 122, 122, 122, 122, 122,
    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122,
    122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 0,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 0, 23, 24, 171, 172, 173, 174, 175, 23, 24,




    23, 24, 23, 24, 176, 177, 178, 179, 21, 23, 24, 21, 23, 24, 21, 21,
    21, 21, 21, 91, 91, 180, 180, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14,
    14, 23, 24, 23, 24, 92, 92, 92, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3,
    18, 3, 3, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181,


    181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181,
    181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 0, 181,
    0, 0, 0, 0, 0, 181, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 91, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20,
    3, 16, 20, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3,
    16, 20, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 2, 3, 3, 3, 14, 91,
    15, 128, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5,
    6, 8, 5, 6, 6, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 92,
    92, 92, 92, 124, 124, 8, 91, 91, 91, 91, 91, 14, 14, 128, 128, 128,
    91, 15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 11, 11, 91,
    91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 91, 91, 91, 15,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 14,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 3, 3, 3, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 15,

    92, 119, 119, 119, 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 91,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 91, 92, 92, 15, 15,
    15, 15, 15, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 92,
    92, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 91, 21, 21, 21, 21, 21, 21, 21, 21, 23, 24,
    23, 24, 182, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 11, 11, 23,
    24, 183, 21, 15, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 184, 185, 186,

    187, 184, 21, 188, 189, 190, 191, 23, 24, 23, 24, 23, 24, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 91, 91, 21, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15,
    92, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 124,
    14, 14, 14, 14, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 14, 14, 4, 14,
    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 124,
    124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15,
    3, 15, 15, 92, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92,
    92, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 92, 92,
    92, 92, 124, 124, 92, 124, 124, 124, 124, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 0, 91, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3,
    15, 15, 15, 15, 15, 92, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 124, 124,
    92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 15, 15, 15, 15,
    15, 15, 15, 15, 92, 124, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 91, 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 124, 92, 124, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 15, 92, 92, 92, 15, 15, 92, 92, 15, 15, 15, 15, 15, 92, 92, 15,
    92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 91, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 124, 92, 92, 124, 124, 3, 3, 15, 91, 91, 124, 92, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 192, 21, 21, 21,
    21, 21, 21, 21, 11, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193,
    193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193,
    193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193,
    193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 15, 15, 15, 124,
    124, 92, 124, 124, 92, 124, 124, 3, 124, 92, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 194, 194, 194,
    194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194,
    194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194,
    194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195,
    195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195,
    195, 195, 195, 195, 195, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 21,
    21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21,
    21, 21, 21, 0, 0, 0, 0, 0, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 0, 15, 0, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,




    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4,


































    14, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,






































    92, 3, 3, 3, 3, 3, 3, 3, 5, 6, 3, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 8, 8, 12, 12, 5,
    6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 5, 6, 3, 3, 3, 3,
    12, 12, 12, 3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7,
    8, 7, 7, 7, 0, 3, 4, 3, 3, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 17, 0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3,
    3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 5, 6, 3, 5, 6, 3, 3, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 91, 91, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 0, 0, 0, 4,
    4, 7, 11, 14, 4, 4, 0, 14, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 17, 17, 17, 14, 14, 0, 0
#if TCL_UTF_MAX > 3
    ,15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18,


    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 18,


    18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 18, 18, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 128, 15, 15, 15, 15, 15, 15,
    15, 15, 128, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,



    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    3, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 128,
    128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 196, 196, 196,



    196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
    196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
    196, 196, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 197, 197,
    197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
    197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
    197, 197, 197, 197, 197, 197, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 196,



    196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
    196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
    196, 196, 196, 196, 196, 196, 196, 0, 0, 0, 0, 197, 197, 197, 197,
    197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
    197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197,










    197, 197, 197, 197, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    0, 0, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18,
    18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18,
    18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0,
    0, 0, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18,
    0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 18, 18, 15, 15, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 92, 92, 92, 0, 92, 92,
    0, 0, 0, 0, 0, 92, 92, 92, 92, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15,





    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 0, 0,
    0, 0, 92, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    15, 15, 15, 15, 15, 15, 15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,

    0, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18,








    18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
    97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
    97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,

    97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102,
    102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
    102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
    102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
    102, 102, 102, 102, 102, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18,
    15, 15, 15, 15, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9,




    9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,


    15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 18, 18, 18, 18, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 124, 92,
    124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124,
    92, 92, 92, 92, 124, 124, 92, 92, 3, 3, 17, 3, 3, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92,
    92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92,
    92, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 124, 124, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 92, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 15,
    15, 15, 15, 3, 3, 3, 3, 92, 92, 92, 92, 3, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 15, 3, 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124,

    92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 3, 3, 3, 92, 0, 15,

    15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,










    15, 15, 15, 15, 15, 15, 92, 124, 124, 124, 92, 92, 92, 92, 92, 92,

    92, 92, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0,

    0, 92, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0,
    15, 15, 15, 15, 15, 0, 92, 92, 15, 124, 124, 92, 124, 124, 124, 124,
    0, 0, 124, 124, 0, 0, 124, 124, 124, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 124, 124, 0, 0, 92, 92, 92, 92,
    92, 92, 92, 0, 0, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92,
    124, 124, 92, 92, 92, 124, 92, 15, 15, 15, 15, 3, 3, 3, 3, 3, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 0, 3, 0, 3, 92, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92,

    92, 92, 92, 124, 92, 124, 124, 124, 124, 92, 92, 124, 92, 92, 15, 15,
    3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 124, 124, 124, 92, 92, 92, 92, 0, 0, 124, 124, 124, 124, 92, 92,
    124, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 15, 15, 15, 15, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92,
    92, 92, 92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0,
    0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 124, 92, 0, 0, 0,
    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 124, 92, 92, 92, 92,
    124, 92, 92, 92, 92, 92, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    18, 18, 3, 3, 3, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,

    124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92, 3,
    0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0,




    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92,


    92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,




    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 15, 92,
    92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 92, 0, 0, 0, 0, 0, 0, 0, 0, 15,

    92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 92, 15, 15, 15, 15, 15, 15,

    15, 15, 0, 0, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 124, 92, 92, 3, 3, 3, 15, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92,
    92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 124, 92, 15, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 0, 124, 92, 92, 92, 92, 92, 92, 92, 124,
    92, 92, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 0, 0, 0,
    92, 0, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 15, 92, 0, 0, 0, 0, 0,
    0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 124, 124, 124, 124, 124, 0, 92, 92, 0, 124, 124, 92,
    124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 124, 3, 3, 0,






    0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,




    128, 128, 128, 128, 128, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0,


    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 92, 92, 92, 92, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92,


    92, 92, 92, 3, 3, 3, 3, 3, 14, 14, 14, 14, 91, 91, 91, 91, 3, 14, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 18, 18,
    18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15,


    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 3, 3, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15,






    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 91, 91, 91,

    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 92, 92, 3, 17, 17, 17,
    17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 124, 124, 92, 92, 92, 14, 14, 14, 124,
    124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 17, 17, 92, 92, 92,
    92, 92, 92, 92, 92, 14, 14, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,



    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 92, 92, 92, 14, 0, 0, 0, 0, 0,








    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,


    0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107,

    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107,

    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 107, 0, 107, 107, 0, 0, 107, 0, 0, 107, 107,
    0, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107,
    21, 21, 21, 21, 0, 21, 0, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21,




    21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107,

    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107,

    0, 107, 107, 107, 107, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107,
    0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,

    21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107,
    0, 107, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107,


    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,


    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    21, 21, 21, 21, 21, 21, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107,

    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21,
    21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21,
    21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
    107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21,
    107, 21, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,

    9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14,

    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 0, 92, 92, 92,







    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 92,


    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 92, 92,
    92, 92, 92, 92, 92, 0, 92, 92, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,





    0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 92, 92, 92, 92, 92, 92,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 198, 198, 198,




    198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198,
    198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14,
    18, 18, 18, 4, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,




    15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0,
    15, 0, 15, 0, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, 15,
    0, 15, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15,





    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,






    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0,
    14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11,
    11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,

    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14,

    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,

    0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14,
    14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,

    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

#endif /* TCL_UTF_MAX > 3 */
};

/*
 * Each group represents a unique set of character attributes.  The attributes
 * are encoded into a 32-bit value as follows:
 *
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
    5, 23, 16, 11, -190078, 24, 2, -30846, 321, 386, -50879, 59522,
    -30911, 76930, -49790, 53825, 52801, 52545, 20289, 51777, 52033,
    53057, -24702, 54081, 53569, -41598, 54593, -33150, 54849, 55873,
    55617, 56129, -14206, 609, 451, 674, 20354, -24767, -14271, -33215,
    2763585, -41663, 2762817, -2768510, -49855, 17729, 18241, -2760318,
    -2759550, -2760062, 53890, 52866, 52610, 51842, 52098, -10833534,
    -10832510, 53122, -10823550, -10830718, 53634, 54146, -2750078,
    -10829950, -2751614, 54658, 54914, -2745982, 55938, -10830462,
    -10824062, 17794, 55682, 18306, 56194, -10818686, -10817918, 4,
    6, -21370, 29761, 9793, 9537, 16449, 16193, 9858, 9602, 8066,
    16514, 16258, 2113, 16002, 14722, 1, 12162, 13954, 2178, 22146,
    20610, -1662, 29826, -15295, 24706, -1727, 20545, 7, 3905, 3970,
    12353, 12418, 8, 1859649, -769822, 9949249, 10, 1601154, 1600898,
    1598594, 1598082, 1598338, 1596546, 1582466, -9027966, -769983,
    -9044862, -976254, -9058174, 15234, -1949375, -1918, -1983, -18814,
    -21886, -25470, -32638, -28542, -32126, -1981, -2174, -18879,
    -2237, 1844610, -21951, -25535, -28607, -32703, -32191, 13, 14,
    -1924287, -2145983, -2115007, 7233, 7298, 4170, 4234, 6749, 6813,
    -2750143, -976319, -2746047, 2763650, 2762882, -2759615, -2751679,
    -2760383, -2760127, -2768575, 1859714, -9044927, -10823615, -12158,
    -10830783, -10833599, -10832575, -10830015, -10817983, -10824127,
    -10818751, 237633, -12223, -10830527, -9058239, 237698, 9949314,
    18, 17, 10305, 10370, 10049, 10114, 8769, 8834
};

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x323C0)
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1F0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.
 */








|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|


|
|

|







1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
    5, 23, 16, 11, -190078, 24, 2, -30846, 321, 386, -50879, 59522,
    -30911, 76930, -49790, 53825, 52801, 52545, 20289, 51777, 52033,
    53057, -24702, 54081, 53569, -41598, 54593, -33150, 54849, 55873,
    55617, 56129, -14206, 609, 451, 674, 20354, -24767, -14271, -33215,
    2763585, -41663, 2762817, -2768510, -49855, 17729, 18241, -2760318,
    -2759550, -2760062, 53890, 52866, 52610, 51842, 52098, -10833534,
    -10832510, 53122, -10823550, -10830718, 53634, 54146, -2750078,
    -10829950, -2751614, 54658, 54914, -2745982, 55938, -10824062,
    17794, 55682, 18306, 56194, -10818686, -10817918, 4, 6, -21370,
    29761, 9793, 9537, 16449, 16193, 9858, 9602, 8066, 16514, 16258,
    2113, 16002, 14722, 1, 12162, 13954, 2178, 22146, 20610, -1662,
    29826, -15295, 24706, -1727, 20545, 7, 3905, 3970, 12353, 12418,
    8, 1859649, -769822, 9949249, 10, 1601154, 1600898, 1598594, 1598082,
    1598338, 1596546, 1582466, -9027966, -769983, -9044862, -976254,
    15234, -1949375, -1918, -1983, -18814, -21886, -25470, -32638,
    -28542, -32126, -1981, -2174, -18879, -2237, 1844610, -21951,
    -25535, -28607, -32703, -32191, 13, 14, -1924287, -2145983, -2115007,
    7233, 7298, 4170, 4234, 6749, 6813, -2750143, -976319, -2746047,
    2763650, 2762882, -2759615, -2751679, -2760383, -2760127, -2768575,
    1859714, -9044927, -10823615, -10830783, -10833599, -10832575,
    -10830015, -10817983, -10824127, -10818751, 237633, 237698, 9949314,

    18, 17, 10305, 10370, 8769, 8834
};

#if TCL_UTF_MAX > 3
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1fffff) >= 0x2fa20)
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1f0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.
 */

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768

/*
 * The following macros extract the fields of the character info.  The
 * GetDelta() macro is complicated because we can't rely on the C compiler
 * to do sign extension on right shifts.
 */

#define GetCaseType(info) (((info) & 0xE0) >> 5)
#define GetCategory(ch) (GetUniCharInfo(ch) & 0x1F)
#define GetDelta(info) ((info) >> 8)

/*
 * This macro extracts the information about a character from the
 * Unicode character tables.
 */

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0x1FFFFF) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]])
#else
#   define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0xFFFF) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]])
#endif







|
|







|
|

|

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647

/*
 * The following macros extract the fields of the character info.  The
 * GetDelta() macro is complicated because we can't rely on the C compiler
 * to do sign extension on right shifts.
 */

#define GetCaseType(info) (((info) & 0xe0) >> 5)
#define GetCategory(ch) (GetUniCharInfo(ch) & 0x1f)
#define GetDelta(info) ((info) >> 8)

/*
 * This macro extracts the information about a character from the
 * Unicode character tables.
 */

#if TCL_UTF_MAX > 3
#   define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0x1fffff) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]])
#else
#   define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0xffff) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]])
#endif

Changes to generic/tclUtf.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#define UNICODE_SELF	0x80

/*
 * The following structures are used when mapping between Unicode (UCS-2) and
 * UTF-8.
 */

static const unsigned char totalBytes[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
#if TCL_UTF_MAX > 3
    4,4,4,4,4,
#else
    1,1,1,1,1,
#endif
    1,1,1,1,1,1,1,1,1,1,1
};

#if TCL_UTF_MAX > 3
static const unsigned char complete[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* Tcl_UtfCharComplete() might point to 2nd byte of valid 4-byte sequence */
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
/* End of "continuation byte section" */
    2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1
};
#else
#   define complete totalBytes
#endif

/*
 * Functions used only in this module.
 */

static int		UtfCount(int ch);
static int		Invalid(const char *src);

/*
 *---------------------------------------------------------------------------
 *
 * UtfCount --
 *
 *	Find the number of bytes in the Utf character "ch".
 *
 * Results:
 *	The return values is the number of bytes in the Utf character "ch".
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static INLINE int
UtfCount(
    int ch)			/* The Unicode character whose size is returned. */
{
    if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
	return 1;
    }
    if (ch <= 0x7FF) {
	return 2;
    }
#if TCL_UTF_MAX > 3
    if (((unsigned)(ch - 0x10000) <= 0xFFFFF)) {
	return 4;
    }
#endif
    return 3;
}

/*
 *---------------------------------------------------------------------------
 *
 * Invalid --
 *
 *	Given a pointer to a two-byte prefix of a well-formed UTF-8 byte
 *	sequence (a lead byte followed by a trail byte) this routine
 *	examines those two bytes to determine whether the sequence is
 *	invalid in UTF-8.  This might be because it is an overlong
 *	encoding, or because it encodes something out of the proper range.
 *
 *	Given a pointer to the bytes \xF8 or \xFC , this routine will
 *	try to read beyond the end of the "bounds" table.  Callers must
 *	prevent this.
 *
 *	Given a pointer to something else (an ASCII byte, a trail byte,
 *	or another byte	that can never begin a valid byte sequence such
 *	as \xF5) this routine returns false.  That makes the routine poorly
 *	named, as it does not detect and report all invalid sequences.
 *
 *	Callers have to take care that this routine does something useful
 *	for their needs.
 *
 * Results:
 *	A boolean.
 *---------------------------------------------------------------------------
 */

static const unsigned char bounds[28] = {
    0x80, 0x80,		/* \xC0 accepts \x80 only */
    0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF,
    0x80, 0xBF,		/* (\xC4 - \xDC) -- all sequences valid */
    0xA0, 0xBF,	/* \xE0\x80 through \xE0\x9F are invalid prefixes */
    0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, /* (\xE4 - \xEC) -- all valid */
#if TCL_UTF_MAX > 3
    0x90, 0xBF,	/* \xF0\x80 through \xF0\x8F are invalid prefixes */
    0x80, 0x8F  /* \xF4\x90 and higher are invalid prefixes */
#else
    0xC0, 0xBF,	/* Not used, but reject all again for safety. */
    0xC0, 0xBF	/* Not used, but reject all again for safety. */
#endif
};

static INLINE int
Invalid(
    const char *src)	/* Points to lead byte of a UTF-8 byte sequence */
{
    unsigned char byte = UCHAR(*src);
    int index;

    if ((byte & 0xC3) == 0xC0) {
	/* Only lead bytes 0xC0, 0xE0, 0xF0, 0xF4 need examination */
	index = (byte - 0xC0) >> 1;
	if (UCHAR(src[1]) < bounds[index] || UCHAR(src[1]) > bounds[index+1]) {
	    /* Out of bounds - report invalid. */
	    return 1;
	}
    }
    return 0;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtf --
 *
 *	Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the
 *	provided buffer. Equivalent to Plan 9 runetochar().







|






|


|

|

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






<

















|

|














|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
120
121
122
123
124
125
#define UNICODE_SELF	0x80

/*
 * The following structures are used when mapping between Unicode (UCS-2) and
 * UTF-8.
 */

static CONST unsigned char totalBytes[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
#if TCL_UTF_MAX > 3
    4,4,4,4,4,4,4,4,
#else
    1,1,1,1,1,1,1,1,
#endif
    1,1,1,1,1,1,1,1
};


















/*
 * Functions used only in this module.
 */

static int		UtfCount(int ch);


/*
 *---------------------------------------------------------------------------
 *
 * UtfCount --
 *
 *	Find the number of bytes in the Utf character "ch".
 *
 * Results:
 *	The return values is the number of bytes in the Utf character "ch".
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

INLINE static int
UtfCount(
    int ch)			/* The Tcl_UniChar whose size is returned. */
{
    if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
	return 1;
    }
    if (ch <= 0x7FF) {
	return 2;
    }
#if TCL_UTF_MAX > 3
    if (((unsigned)(ch - 0x10000) <= 0xFFFFF)) {
	return 4;
    }
#endif
    return 3;
}






























































/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtf --
 *
 *	Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the
 *	provided buffer. Equivalent to Plan 9 runetochar().
229
230
231
232
233
234
235
























236
237
238
239
240
241
242
    if (ch >= 0) {
	if (ch <= 0x7FF) {
	    buf[1] = (char) ((ch | 0x80) & 0xBF);
	    buf[0] = (char) ((ch >> 6) | 0xC0);
	    return 2;
	}
	if (ch <= 0xFFFF) {
























	    goto three;
	}

#if TCL_UTF_MAX > 3
	if (ch <= 0x10FFFF) {
	    buf[3] = (char) ((ch | 0x80) & 0xBF);
	    buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    if (ch >= 0) {
	if (ch <= 0x7FF) {
	    buf[1] = (char) ((ch | 0x80) & 0xBF);
	    buf[0] = (char) ((ch >> 6) | 0xC0);
	    return 2;
	}
	if (ch <= 0xFFFF) {
#if TCL_UTF_MAX == 4
	    if ((ch & 0xF800) == 0xD800) {
		if (ch & 0x0400) {
		    /* Low surrogate */
		    if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80)
			    && ((buf[2] & 0xCF) == 0)) {
			/* Previous Tcl_UniChar was a High surrogate, so combine */
			buf[3] = (char) ((ch & 0x3F) | 0x80);
			buf[2] |= (char) (((ch >> 6) & 0x0F) | 0x80);
			return 4;
		    }
		    /* Previous Tcl_UniChar was not a High surrogate, so just output */
		} else {
		    /* High surrogate */
		    ch += 0x40;
		    /* Fill buffer with specific 3-byte (invalid) byte combination,
		       so following Low surrogate can recognize it and combine */
		    buf[2] = (char) ((ch << 4) & 0x30);
		    buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80);
		    buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0);
		    return 0;
		}
	    }
#endif
	    goto three;
	}

#if TCL_UTF_MAX > 3
	if (ch <= 0x10FFFF) {
	    buf[3] = (char) ((ch | 0x80) & 0xBF);
	    buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
 *	None.
 *
 *---------------------------------------------------------------------------
 */

char *
Tcl_UniCharToUtfDString(
    const Tcl_UniChar *uniStr,	/* Unicode string to convert to UTF-8. */
    int uniLength,		/* Length of Unicode string in Tcl_UniChars
				 * (must be >= 0). */
    Tcl_DString *dsPtr)		/* UTF-8 representation of string is appended
				 * to this previously initialized DString. */
{
    const Tcl_UniChar *w, *wEnd;
    char *p, *string;
    int oldLength;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length *
     * TCL_UTF_MAX.
     */

    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * TCL_UTF_MAX);
    string = Tcl_DStringValue(dsPtr) + oldLength;

    p = string;
    wEnd = uniStr + uniLength;
    for (w = uniStr; w < wEnd; ) {
	p += Tcl_UniCharToUtf(*w, p);
	w++;







|





|









|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
 *	None.
 *
 *---------------------------------------------------------------------------
 */

char *
Tcl_UniCharToUtfDString(
    CONST Tcl_UniChar *uniStr,	/* Unicode string to convert to UTF-8. */
    int uniLength,		/* Length of Unicode string in Tcl_UniChars
				 * (must be >= 0). */
    Tcl_DString *dsPtr)		/* UTF-8 representation of string is appended
				 * to this previously initialized DString. */
{
    CONST Tcl_UniChar *w, *wEnd;
    char *p, *string;
    int oldLength;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length *
     * TCL_UTF_MAX.
     */

    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX);
    string = Tcl_DStringValue(dsPtr) + oldLength;

    p = string;
    wEnd = uniStr + uniLength;
    for (w = uniStr; w < wEnd; ) {
	p += Tcl_UniCharToUtf(*w, p);
	w++;
317
318
319
320
321
322
323









324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395



396















397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
 *	The caller must ensure that the source buffer is long enough that this
 *	routine does not run off the end and dereference non-existent memory
 *	looking for trail bytes. If the source buffer is known to be '\0'
 *	terminated, this cannot happen. Otherwise, the caller should call
 *	Tcl_UtfCharComplete() before calling this routine to ensure that
 *	enough bytes remain in the string.
 *









 * Results:
 *	*chPtr is filled with the Tcl_UniChar, and the return value is the
 *	number of bytes from the UTF-8 string that were consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    Tcl_UniChar *chPtr)/* Filled with the Tcl_UniChar represented by
				 * the UTF-8 string. */
{
    Tcl_UniChar byte;

    /*
     * Unroll 1 to 3 (or 4) byte UTF-8 sequences.
     */

    byte = UCHAR(*src);
    if (byte < 0xC0) {
	/*
	 * Handles properly formed UTF-8 characters between 0x01 and 0x7F.
	 * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
	 * characters representing themselves.
	 */

	*chPtr = byte;
	return 1;
    } else if (byte < 0xE0) {
	if ((src[1] & 0xC0) == 0x80) {
	    /*
	     * Two-byte-character lead-byte followed by a trail-byte.
	     */

	    *chPtr = (((byte & 0x1F) << 6) | (src[1] & 0x3F));
	    if ((unsigned)(*chPtr - 1) >= (UNICODE_SELF - 1)) {
		return 2;
	    }
	}

	/*
	 * A two-byte-character lead-byte not followed by trail-byte
	 * represents itself.
	 */
    } else if (byte < 0xF0) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
	    /*
	     * Three-byte-character lead byte followed by two trail bytes.
	     */

	    *chPtr = (((byte & 0x0F) << 12)
		    | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F));
	    if (*chPtr > 0x7FF) {
		return 3;
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
#if TCL_UTF_MAX > 3
    else if (byte < 0xF5) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) {
	    /*
	     * Four-byte-character lead byte followed by three trail bytes.
	     */



	    *chPtr = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)















		    | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
	    if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) {
		return 4;
	    }

	}

	/*
	 * A four-byte-character lead-byte not followed by three trail-bytes
	 * represents itself.
	 */
    }
#endif

    *chPtr = byte;
    return 1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfToUniCharDString --







>
>
>
>
>
>
>
>
>












|
|


|


|


|







|







|















|












|




>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>



|





|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
 *	The caller must ensure that the source buffer is long enough that this
 *	routine does not run off the end and dereference non-existent memory
 *	looking for trail bytes. If the source buffer is known to be '\0'
 *	terminated, this cannot happen. Otherwise, the caller should call
 *	Tcl_UtfCharComplete() before calling this routine to ensure that
 *	enough bytes remain in the string.
 *
 *	If TCL_UTF_MAX == 4, special handling of Surrogate pairs is done:
 *	For any UTF-8 string containing a character outside of the BMP, the
 *	first call to this function will fill *chPtr with the high surrogate
 *	and generate a return value of 0. Calling Tcl_UtfToUniChar again
 *	will produce the low surrogate and a return value of 4. Because *chPtr
 *	is used to remember whether the high surrogate is already produced, it
 *	is recommended to initialize the variable it points to as 0 before
 *	the first call to Tcl_UtfToUniChar is done.
 *
 * Results:
 *	*chPtr is filled with the Tcl_UniChar, and the return value is the
 *	number of bytes from the UTF-8 string that were consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfToUniChar(
    register CONST char *src,	/* The UTF-8 string. */
    register Tcl_UniChar *chPtr)/* Filled with the Tcl_UniChar represented by
				 * the UTF-8 string. */
{
    register int byte;

    /*
     * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
     */

    byte = *((unsigned char *) src);
    if (byte < 0xC0) {
	/*
	 * Handles properly formed UTF-8 characters between 0x01 and 0x7F.
	 * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
	 * characters representing themselves.
	 */

	*chPtr = (Tcl_UniChar) byte;
	return 1;
    } else if (byte < 0xE0) {
	if ((src[1] & 0xC0) == 0x80) {
	    /*
	     * Two-byte-character lead-byte followed by a trail-byte.
	     */

	    *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (src[1] & 0x3F));
	    if ((unsigned)(*chPtr - 1) >= (UNICODE_SELF - 1)) {
		return 2;
	    }
	}

	/*
	 * A two-byte-character lead-byte not followed by trail-byte
	 * represents itself.
	 */
    } else if (byte < 0xF0) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
	    /*
	     * Three-byte-character lead byte followed by two trail bytes.
	     */

	    *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12)
		    | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F));
	    if (*chPtr > 0x7FF) {
		return 3;
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
#if TCL_UTF_MAX > 3
    else if (byte < 0xF8) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) {
	    /*
	     * Four-byte-character lead byte followed by three trail bytes.
	     */
#if TCL_UTF_MAX == 4
	    Tcl_UniChar surrogate;

	    byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
		    | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)) - 0x10000;
	    surrogate = (Tcl_UniChar) (0xD800 + (byte >> 10));
	    if (byte & 0x100000) {
		/* out of range, < 0x10000 or > 0x10ffff */
	    } else if (*chPtr != surrogate) {
		/* produce high surrogate, but don't advance source pointer */
		*chPtr = surrogate;
		return 0;
	    } else {
		/* produce low surrogate, and advance source pointer */
		*chPtr = (Tcl_UniChar) (0xDC00 | (byte & 0x3FF));
		return 4;
	    }
#else
	    *chPtr = (Tcl_UniChar) (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
		    | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
	    if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) {
		return 4;
	    }
#endif
	}

	/*
	 * A four-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
#endif

    *chPtr = (Tcl_UniChar) byte;
    return 1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfToUniCharDString --
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_UniChar *
Tcl_UtfToUniCharDString(
    const char *src,		/* UTF-8 string to convert to Unicode. */
    int length,			/* Length of UTF-8 string in bytes, or -1 for
				 * strlen(). */
    Tcl_DString *dsPtr)		/* Unicode representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    Tcl_UniChar *w, *wString;
    const char *p;
    int oldLength;
    /* Pointer to the end of string. Never read endPtr[0] */
    const char *endPtr;
    /* Pointer to last byte where optimization still can be used */
    const char *optPtr;

    if (length < 0) {
	length = strlen(src);
    }

    /*
     * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in
     * bytes.
     */

    oldLength = Tcl_DStringLength(dsPtr);

    Tcl_DStringSetLength(dsPtr,
	    oldLength + ((length + 1) * sizeof(Tcl_UniChar)));
    wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);

    w = wString;
    p = src;
    endPtr = src + length;
    optPtr = endPtr - ((TCL_UTF_MAX > 3) ? 4 : 3) ;
    while (p <= optPtr) {
	p += TclUtfToUniChar(p, w);
	w++;
    }
    while (p < endPtr) {
	if (Tcl_UtfCharComplete(p, endPtr-p)) {
	    p += TclUtfToUniChar(p, w);
	    w++;
	} else {
	    *w++ = UCHAR(*p++);
	}
    }
    *w = '\0';
    Tcl_DStringSetLength(dsPtr,
	    oldLength + ((char *) w - (char *) wString));

    return wString;
}

/*
 *---------------------------------------------------------------------------
 *







|







|

<
<
<
<











<

|



<
|
<
<
<
<
<
|
<
|
|
<
<
|
<


|







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416




417
418
419
420
421
422
423
424
425
426
427

428
429
430
431
432

433





434

435
436


437

438
439
440
441
442
443
444
445
446
447
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_UniChar *
Tcl_UtfToUniCharDString(
    CONST char *src,		/* UTF-8 string to convert to Unicode. */
    int length,			/* Length of UTF-8 string in bytes, or -1 for
				 * strlen(). */
    Tcl_DString *dsPtr)		/* Unicode representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    Tcl_UniChar *w, *wString;
    CONST char *p, *end;
    int oldLength;





    if (length < 0) {
	length = strlen(src);
    }

    /*
     * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in
     * bytes.
     */

    oldLength = Tcl_DStringLength(dsPtr);

    Tcl_DStringSetLength(dsPtr,
	    (int) ((oldLength + length + 1) * sizeof(Tcl_UniChar)));
    wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);

    w = wString;

    end = src + length;





    for (p = src; p < end; ) {

	p += TclUtfToUniChar(p, w);
	w++;


    }

    *w = '\0';
    Tcl_DStringSetLength(dsPtr,
	    (oldLength + ((char *) w - (char *) wString)));

    return wString;
}

/*
 *---------------------------------------------------------------------------
 *
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfCharComplete(
    const char *src,		/* String to check if first few bytes contain
				 * a complete UTF-8 character. */
    int length)			/* Length of above string in bytes. */
{
    return length >= complete[UCHAR(*src)];
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_NumUtfChars --
 *







|



|







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfCharComplete(
    CONST char *src,		/* String to check if first few bytes contain
				 * a complete UTF-8 character. */
    int length)			/* Length of above string in bytes. */
{
    return length >= totalBytes[(unsigned char)*src];
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_NumUtfChars --
 *
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566
567



568
569
570
571
572
573
574
575
576
577
578



579



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610


611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645


646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_NumUtfChars(
    const char *src,	/* The UTF-8 string to measure. */
    int length)		/* The length of the string in bytes, or -1
			 * for strlen(string). */
{
    Tcl_UniChar ch;
    int i = 0;

    if (length < 0) {

	/* string is NUL-terminated, so TclUtfToUniChar calls are safe. */
	while ((*src != '\0') && (i < INT_MAX)) {
	    src += TclUtfToUniChar(src, &ch);
	    i++;
	}
    } else {
	/* Will return value between 0 and length. No overflow checks. */

	/* Pointer to the end of string. Never read endPtr[0] */
	const char *endPtr = src + length;
	/* Pointer to last byte where optimization still can be used */
	const char *optPtr = endPtr - ((TCL_UTF_MAX > 3) ? 4 : 3);


	/*
	 * Optimize away the call in this loop. Justified because...
	 * when (src <= optPtr), (endPtr - src) >= (endPtr - optPtr)
	 * By initialization above (endPtr - optPtr) = TCL_UTF_MAX
	 * So (endPtr - src) >= TCL_UTF_MAX, and passing that to
	 * Tcl_UtfCharComplete we know will cause return of 1.
	 */
	while (src <= optPtr
		/* && Tcl_UtfCharComplete(src, endPtr - src) */ ) {
	    src += TclUtfToUniChar(src, &ch);
	    i++;
	}



	/* Loop over the remaining string where call must happen */
	while (src < endPtr) {
	    if (Tcl_UtfCharComplete(src, endPtr - src)) {
		src += TclUtfToUniChar(src, &ch);
	    } else {
		/*
		 * src points to incomplete UTF-8 sequence
		 * Treat first byte as character and count it
		 */
		src++;
	    }



	    i++;



	}
    }
    return i;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindFirst --
 *
 *	Returns a pointer to the first occurrence of the given Unicode character
 *	in the NULL-terminated UTF-8 string. The NULL terminator is considered
 *	part of the UTF-8 string. Equivalent to Plan 9 utfrune().
 *
 * Results:
 *	As above. If the Unicode character does not exist in the given string,
 *	the return value is NULL.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfFindFirst(
    const char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Tcl_UniChar to search for. */
{
    while (1) {
	Tcl_UniChar find;


	int len = TclUtfToUniChar(src, &find);
	if (find == ch) {
	    return src;
	}
	if (*src == '\0') {
	    return NULL;
	}
	src += len;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindLast --
 *
 *	Returns a pointer to the last occurance of the given Unicode character
 *	in the NULL-terminated UTF-8 string. The NULL terminator is considered
 *	part of the UTF-8 string. Equivalent to Plan 9 utfrrune().
 *
 * Results:
 *	As above. If the Unicode character does not exist in the given string, the
 *	return value is NULL.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfFindLast(
    const char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Unicode character to search for. */
{


    const char *last = NULL;


    while (1) {
	Tcl_UniChar find;
	int len = TclUtfToUniChar(src, &find);

	if (find == ch) {
	    last = src;
	}
	if (*src == '\0') {
	    break;
	}
	src += len;
    }
    return last;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfNext --
 *
 *	Given a pointer to some location in a UTF-8 string, Tcl_UtfNext
 *	returns a pointer to the next UTF-8 character in the string.
 *	The caller must not ask for the next character after the last
 *	character in the string if the string is not terminated by a null
 *	character.
 *
 * Results:
 *	The return value is the pointer to the next character in the UTF-8
 *	string.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfNext(
    const char *src)		/* The current location in the string. */
{
    int left;
    const char *next;

#if TCL_UTF_MAX > 3
    if (((*src) & 0xC0) == 0x80) {
	/* Continuation byte, so we start 'inside' a (possible valid) UTF-8
	 * sequence. Since we are not allowed to access src[-1], we cannot
	 * check if the sequence is actually valid, the best we can do is
	 * just assume it is valid and locate the end. */
	if ((((*++src) & 0xC0) == 0x80) && (((*++src) & 0xC0) == 0x80)) {
	    ++src;
	}
	return src;
    }
#endif

    left = totalBytes[UCHAR(*src)];
    next = src + 1;
    while (--left) {
	if ((*next & 0xC0) != 0x80) {
	    /*
	     * src points to non-trail byte; We ran out of trail bytes
	     * before the needs of the lead byte were satisfied.
	     * Let the (malformed) lead byte alone be a character
	     */
	    return src + 1;
	}
	next++;
    }
    /*
     * Call Invalid() here only if required conditions are met:
     *    src[0] is known a lead byte.
     *    src[1] is known a trail byte.
     * Especially important to prevent calls when src[0] == '\xF8' or '\xFC'
     * See tests utf-6.37 through utf-6.43 through valgrind or similar tool.
     */
    if ((next == src + 1) || Invalid(src)) {
	return src + 1;
    }
    return next;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfPrev --
 *







|
|
|


|

<
>
|
<
<
<
<
<
<
|
<
<
<
<
|
>
|
|
|
|
<
<
<
|
<



>
>
>
|

<
|
<
<
<
<
<
|
|
>
>
>

>
>
>










|
|



|
|







|

|


|
|
>
>
|















|
|



|








|

|
|

>
>
|

>

<
|
<
















|
|
|
<
<











|

|

<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<







486
487
488
489
490
491
492
493
494
495
496
497
498
499

500
501






502




503
504
505
506
507
508



509

510
511
512
513
514
515
516
517

518





519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621


622
623
624
625
626
627
628
629
630
631
632
633
634
635
636


637








638













639














640
641
642
643
644
645
646
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_NumUtfChars(
    register CONST char *src,	/* The UTF-8 string to measure. */
    int length)			/* The length of the string in bytes, or -1
				 * for strlen(string). */
{
    Tcl_UniChar ch;
    register int i;


    /*
     * The separate implementations are faster.






     *




     * Since this is a time-sensitive function, we also do the check for the
     * single-byte char case specially.
     */

    i = 0;
    if (length < 0) {



	while (*src != '\0') {

	    src += TclUtfToUniChar(src, &ch);
	    i++;
	}
	if (i < 0) i = INT_MAX; /* Bug [2738427] */
    } else {
	register const char *endPtr = src + length - TCL_UTF_MAX;

	while (src < endPtr) {

	    src += TclUtfToUniChar(src, &ch);





	    i++;
	}
	endPtr += TCL_UTF_MAX;
	while ((src < endPtr) && Tcl_UtfCharComplete(src, endPtr - src)) {
	    src += TclUtfToUniChar(src, &ch);
	    i++;
	}
	if (src < endPtr) {
	    i += endPtr - src;
	}
    }
    return i;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindFirst --
 *
 *	Returns a pointer to the first occurance of the given Tcl_UniChar in
 *	the NULL-terminated UTF-8 string. The NULL terminator is considered
 *	part of the UTF-8 string. Equivalent to Plan 9 utfrune().
 *
 * Results:
 *	As above. If the Tcl_UniChar does not exist in the given string, the
 *	return value is NULL.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfFindFirst(
    CONST char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Tcl_UniChar to search for. */
{
    int len;
    Tcl_UniChar find;

    while (1) {
	len = TclUtfToUniChar(src, &find);
	if (find == ch) {
	    return src;
	}
	if (*src == '\0') {
	    return NULL;
	}
	src += len;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindLast --
 *
 *	Returns a pointer to the last occurance of the given Tcl_UniChar in
 *	the NULL-terminated UTF-8 string. The NULL terminator is considered
 *	part of the UTF-8 string. Equivalent to Plan 9 utfrrune().
 *
 * Results:
 *	As above. If the Tcl_UniChar does not exist in the given string, the
 *	return value is NULL.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfFindLast(
    CONST char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Tcl_UniChar to search for. */
{
    int len;
    Tcl_UniChar find;
    CONST char *last;

    last = NULL;
    while (1) {

	len = TclUtfToUniChar(src, &find);

	if (find == ch) {
	    last = src;
	}
	if (*src == '\0') {
	    break;
	}
	src += len;
    }
    return last;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfNext --
 *
 *	Given a pointer to some current location in a UTF-8 string, move
 *	forward one character. The caller must ensure that they are not asking
 *	for the next character after the last character in the string.


 *
 * Results:
 *	The return value is the pointer to the next character in the UTF-8
 *	string.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfNext(
    CONST char *src)		/* The current location in the string. */
{


    Tcl_UniChar ch;






















    return src + TclUtfToUniChar(src, &ch);














}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfPrev --
 *
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762

763

764

765

766
767

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866


867

868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfPrev(
    const char *src,		/* A location in a UTF-8 string. */
    const char *start)		/* Pointer to the beginning of the string */

{
    int trailBytesSeen = 0;	/* How many trail bytes have been verified? */
    const char *fallback = src - 1;
				/* If we cannot find a lead byte that might
				 * start a prefix of a valid UTF byte sequence,
				 * we will fallback to a one-byte back step */
    const char *look = fallback;
				/* Start search at the fallback position */



    /* Quick boundary case exit. */

    if (fallback <= start) {

	return start;
    }


    do {
	unsigned char byte = UCHAR(look[0]);

	if (byte < 0x80) {
	    /*
	     * Single byte character. Either this is a correct previous
	     * character, or it is followed by at least one trail byte
	     * which indicates a malformed sequence. In either case the
	     * correct result is to return the fallback.
	     */
	    return fallback;
	}
	if (byte >= 0xC0) {
	    /* Non-trail byte; May be multibyte lead. */

	    if ((trailBytesSeen == 0)
		/*
		 * We've seen no trailing context to use to check
		 * anything. From what we know, this non-trail byte
		 * is a prefix of a previous character, and accepting
		 * it (the fallback) is correct.
		 */

		    || (trailBytesSeen >= totalBytes[byte])) {
		/*
		 * That is, (1 + trailBytesSeen > needed).
		 * We've examined more bytes than needed to complete
		 * this lead byte. No matter about well-formedness or
		 * validity, the sequence starting with this lead byte
		 * will never include the fallback location, so we must
		 * return the fallback location. See test utf-7.17
		 */
		return fallback;
	    }

	    /*
	     * trailBytesSeen > 0, so we can examine look[1] safely.
	     * Use that capability to screen out invalid sequences.
	     */

	    if (Invalid(look)) {
		/* Reject */
		return fallback;
	    }
	    return (const char *)look;
	}

	/* We saw a trail byte. */
	trailBytesSeen++;

	if ((const char *)look == start) {
	    /*
	     * Do not read before the start of the string
	     *
	     * If we get here, we've examined bytes at every location
	     * >= start and < src and all of them are trail bytes,
	     * including (*start).  We need to return our fallback
	     * and exit this loop before we run past the start of the string.
	     */
	    return fallback;
	}

	/* Continue the search backwards... */
	look--;
    } while (trailBytesSeen < (TCL_UTF_MAX < 4 ? 3 : 4));

    /*
     * We've seen 3 trail bytes, so we know there will not be a
     * properly formed byte sequence to find, and we can stop looking,
     * accepting the fallback.
     */
    return fallback;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharAtIndex --
 *
 *	Returns the Tcl_UniChar represented at the specified character
 *	(not byte) position in the UTF-8 string.
 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharAtIndex(
    const char *src,	/* The UTF-8 string to dereference. */
    int index)		/* The position of the desired character. */
{
    Tcl_UniChar ch;



    TclUtfToUniChar(Tcl_UtfAtIndex(src, index), &ch);

    return ch;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfAtIndex --
 *
 *	Returns a pointer to the specified character (not byte) position in
 *	the UTF-8 string.
 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfAtIndex(
    const char *src,	/* The UTF-8 string. */
    int index)		/* The position of the desired character. */
{
    Tcl_UniChar ch;

    while (index-- > 0) {

	src += TclUtfToUniChar(src, &ch);
    }
    return src;
}

/*
 *---------------------------------------------------------------------------







|

|
|
>

<
<
<
<
<
|
<
>

>
|
>
|
>
|
|
>
|
<
|
<

<
<
<
<
<
<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
<
<
<
<
<
|







|













|
|



>
>
|
>




















|

|
|



|
>







656
657
658
659
660
661
662
663
664
665
666
667
668





669

670
671
672
673
674
675
676
677
678
679
680

681

682






683
684
685



















686
687





























688

689





690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfPrev(
    CONST char *src,		/* The current location in the string. */
    CONST char *start)		/* Pointer to the beginning of the string, to
				 * avoid going backwards too far. */
{





    CONST char *look;

    int i, byte;

    src--;
    look = src;
    for (i = 0; i < TCL_UTF_MAX; i++) {
	if (look < start) {
	    if (src < start) {
		src = start;
	    }
	    break;
	}

	byte = *((unsigned char *) look);

	if (byte < 0x80) {






	    break;
	}
	if (byte >= 0xC0) {



















	    return look;
	}





























	look--;

    }





    return src;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharAtIndex --
 *
 *	Returns the Unicode character represented at the specified character
 *	(not byte) position in the UTF-8 string.
 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharAtIndex(
    register CONST char *src,	/* The UTF-8 string to dereference. */
    register int index)		/* The position of the desired character. */
{
    Tcl_UniChar ch;

    while (index >= 0) {
	index--;
	src += TclUtfToUniChar(src, &ch);
    }
    return ch;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfAtIndex --
 *
 *	Returns a pointer to the specified character (not byte) position in
 *	the UTF-8 string.
 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfAtIndex(
    register CONST char *src,	/* The UTF-8 string. */
    register int index)		/* The position of the desired character. */
{
    Tcl_UniChar ch;

    while (index > 0) {
	index--;
	src += TclUtfToUniChar(src, &ch);
    }
    return src;
}

/*
 *---------------------------------------------------------------------------
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
 *	buffer overruns should occur.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfBackslash(
    const char *src,		/* Points to the backslash character of a
				 * backslash sequence. */
    int *readPtr,		/* Fill in with number of characters read from
				 * src, unless NULL. */
    char *dst)			/* Filled with the bytes represented by the
				 * backslash sequence. */
{
#define LINE_LENGTH 128
    int numRead;
    int result;

    result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst);
    if (numRead == LINE_LENGTH) {
	/*
	 * We ate a whole line. Pay the price of a strlen()
	 */

	result = TclParseBackslash(src, strlen(src), &numRead, dst);
    }
    if (readPtr != NULL) {
	*readPtr = numRead;
    }
    return result;
}








|
















|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
 *	buffer overruns should occur.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfBackslash(
    CONST char *src,		/* Points to the backslash character of a
				 * backslash sequence. */
    int *readPtr,		/* Fill in with number of characters read from
				 * src, unless NULL. */
    char *dst)			/* Filled with the bytes represented by the
				 * backslash sequence. */
{
#define LINE_LENGTH 128
    int numRead;
    int result;

    result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst);
    if (numRead == LINE_LENGTH) {
	/*
	 * We ate a whole line. Pay the price of a strlen()
	 */

	result = TclParseBackslash(src, (int)strlen(src), &numRead, dst);
    }
    if (readPtr != NULL) {
	*readPtr = numRead;
    }
    return result;
}

971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

int
Tcl_UtfToUpper(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, upChar;
    char *src, *dst;
    int len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUniChar(src, &ch);
	upChar = Tcl_UniCharToUpper(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the upper case
	 * char to dst if its size is <= the original char.
	 */

	if (len < UtfCount(upChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(upChar, dst);
	}
	src += len;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------







|







|








|
|
|



|







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

int
Tcl_UtfToUpper(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, upChar;
    char *src, *dst;
    int bytes;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	bytes = TclUtfToUniChar(src, &ch);
	upChar = Tcl_UniCharToUpper(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the upper case
	 * char to dst if its size is <= the original char.
	 */

	if (bytes < UtfCount(upChar)) {
	    memcpy(dst, src, (size_t) bytes);
	    dst += bytes;
	} else {
	    dst += Tcl_UniCharToUtf(upChar, dst);
	}
	src += bytes;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

int
Tcl_UtfToLower(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, lowChar;
    char *src, *dst;
    int len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUniChar(src, &ch);
	lowChar = Tcl_UniCharToLower(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the lower case
	 * char to dst if its size is <= the original char.
	 */

	if (len < UtfCount(lowChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------







|







|








|
|
|



|







878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915

int
Tcl_UtfToLower(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, lowChar;
    char *src, *dst;
    int bytes;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	bytes = TclUtfToUniChar(src, &ch);
	lowChar = Tcl_UniCharToLower(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the lower case
	 * char to dst if its size is <= the original char.
	 */

	if (bytes < UtfCount(lowChar)) {
	    memcpy(dst, src, (size_t) bytes);
	    dst += bytes;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += bytes;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

int
Tcl_UtfToTitle(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, titleChar, lowChar;
    char *src, *dst;
    int len;

    /*
     * Capitalize the first character and then lowercase the rest of the
     * characters until we get to a null.
     */

    src = dst = str;

    if (*src) {
	len = TclUtfToUniChar(src, &ch);
	titleChar = Tcl_UniCharToTitle(ch);

	if (len < UtfCount(titleChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(titleChar, dst);
	}
	src += len;
    }
    while (*src) {
	len = TclUtfToUniChar(src, &ch);
	lowChar = ch;
	/* Special exception for Georgian Asomtavruli chars, no titlecase. */
	if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
	    lowChar = Tcl_UniCharToLower(lowChar);
	}

	if (len < UtfCount(lowChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------







|









|


|
|
|



|


|






|
|
|



|







932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

int
Tcl_UtfToTitle(
    char *str)			/* String to convert in place. */
{
    Tcl_UniChar ch, titleChar, lowChar;
    char *src, *dst;
    int bytes;

    /*
     * Capitalize the first character and then lowercase the rest of the
     * characters until we get to a null.
     */

    src = dst = str;

    if (*src) {
	bytes = TclUtfToUniChar(src, &ch);
	titleChar = Tcl_UniCharToTitle(ch);

	if (bytes < UtfCount(titleChar)) {
	    memcpy(dst, src, (size_t) bytes);
	    dst += bytes;
	} else {
	    dst += Tcl_UniCharToUtf(titleChar, dst);
	}
	src += bytes;
    }
    while (*src) {
	bytes = TclUtfToUniChar(src, &ch);
	lowChar = ch;
	/* Special exception for Georgian Asomtavruli chars, no titlecase. */
	if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
	    lowChar = Tcl_UniCharToLower(lowChar);
	}

	if (bytes < UtfCount(lowChar)) {
	    memcpy(dst, src, (size_t) bytes);
	    dst += bytes;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += bytes;
    }
    *dst = '\0';
    return (dst - str);
}

/*
 *----------------------------------------------------------------------
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpUtfNcmp2(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    unsigned long numBytes)	/* Number of *bytes* to compare. */
{
    /*
     * We can't simply call 'memcmp(cs, ct, numBytes);' because we need to
     * check for Tcl's \xC0\x80 non-utf-8 null encoding. Otherwise utf-8 lexes
     * fine in the strcmp manner.
     */

    int result = 0;

    for ( ; numBytes != 0; numBytes--, cs++, ct++) {
	if (*cs != *ct) {
	    result = UCHAR(*cs) - UCHAR(*ct);
	    break;
	}
    }







|
|








|







992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpUtfNcmp2(
    CONST char *cs,		/* UTF string to compare to ct. */
    CONST char *ct,		/* UTF string cs is compared to. */
    unsigned long numBytes)	/* Number of *bytes* to compare. */
{
    /*
     * We can't simply call 'memcmp(cs, ct, numBytes);' because we need to
     * check for Tcl's \xC0\x80 non-utf-8 null encoding. Otherwise utf-8 lexes
     * fine in the strcmp manner.
     */

    register int result = 0;

    for ( ; numBytes != 0; numBytes--, cs++, ct++) {
	if (*cs != *ct) {
	    result = UCHAR(*cs) - UCHAR(*ct);
	    break;
	}
    }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213










1214
1215
1216
1217
1218
1219
1220
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    unsigned long numChars)	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;

    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
     * pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
     * (the byte 0x01.)
     */

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes. This should be called
	 * only when both strings are of at least n chars long (no need for \0
	 * check)
	 */

	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {










	    return (ch1 - ch2);
	}
    }
    return 0;
}

/*







|
|




















>
>
>
>
>
>
>
>
>
>







1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcmp(
    CONST char *cs,		/* UTF string to compare to ct. */
    CONST char *ct,		/* UTF string cs is compared to. */
    unsigned long numChars)	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;

    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
     * pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
     * (the byte 0x01.)
     */

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes. This should be called
	 * only when both strings are of at least n chars long (no need for \0
	 * check)
	 */

	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    return (ch1 - ch2);
	}
    }
    return 0;
}

/*
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253










1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286

1287
1288
1289
1290
1291
1292










1293
1294
1295
1296
1297
1298
1299
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcasecmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    unsigned long numChars)	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;
    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {










	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return (ch1 - ch2);
	    }
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclUtfCasecmp --
 *
 *	Compare UTF chars of string cs to string ct case insensitively.
 *	Replacement for strcasecmp in Tcl core, in places where UTF-8 should
 *	be handled.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUtfCasecmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct)		/* UTF string cs is compared to. */
{

    Tcl_UniChar ch1, ch2;

    while (*cs && *ct) {
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {










	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return ch1 - ch2;
	    }
	}
    }







|
|












>
>
>
>
>
>
>
>
>
>













|
















|
|

>
|

<



>
>
>
>
>
>
>
>
>
>







1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcasecmp(
    CONST char *cs,		/* UTF string to compare to ct. */
    CONST char *ct,		/* UTF string cs is compared to. */
    unsigned long numChars)	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;
    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return (ch1 - ch2);
	    }
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcasecmp --
 *
 *	Compare UTF chars of string cs to string ct case insensitively.
 *	Replacement for strcasecmp in Tcl core, in places where UTF-8 should
 *	be handled.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUtfCasecmp(
    CONST char *cs,		/* UTF string to compare to ct. */
    CONST char *ct)		/* UTF string cs is compared to. */
{
    while (*cs && *ct) {
	Tcl_UniChar ch1, ch2;


	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX == 4
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return ch1 - ch2;
	    }
	}
    }
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToUpper(
    int ch)			/* Unicode character to convert. */
{
#if TCL_UTF_MAX > 3
    if (!UNICODE_OUT_OF_RANGE(ch)) {
#endif
	int info = GetUniCharInfo(ch);

	if (GetCaseType(info) & 0x04) {
	    ch -= GetDelta(info);
	}
#if TCL_UTF_MAX > 3
    }
    /* Clear away extension bits, if any */
    ch &= 0x1FFFFF;
#endif
    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToLower --







<
<
<
|

|
|
|
<
<
<
<
<







1201
1202
1203
1204
1205
1206
1207



1208
1209
1210
1211
1212





1213
1214
1215
1216
1217
1218
1219
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToUpper(
    int ch)			/* Unicode character to convert. */
{



    int info = GetUniCharInfo(ch);

    if (GetCaseType(info) & 0x04) {
	ch -= GetDelta(info);
    }





    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToLower --
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToLower(
    int ch)			/* Unicode character to convert. */
{
#if TCL_UTF_MAX > 3
    if (!UNICODE_OUT_OF_RANGE(ch)) {
#endif
	int info = GetUniCharInfo(ch);
	int mode = GetCaseType(info);

	if ((mode & 0x02) && (mode != 0x7)) {
	    ch += GetDelta(info);
	}
#if TCL_UTF_MAX > 3
    }
    /* Clear away extension bits, if any */
    ch &= 0x1FFFFF;
#endif
    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToTitle --







<
<
<
|
|

|
|
|
<
<
<
<
<







1229
1230
1231
1232
1233
1234
1235



1236
1237
1238
1239
1240
1241





1242
1243
1244
1245
1246
1247
1248
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToLower(
    int ch)			/* Unicode character to convert. */
{



    int info = GetUniCharInfo(ch);
    int mode = GetCaseType(info);

    if ((mode & 0x02) && (mode != 0x7)) {
	ch += GetDelta(info);
    }





    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToTitle --
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToTitle(
    int ch)			/* Unicode character to convert. */
{
#if TCL_UTF_MAX > 3
    if (!UNICODE_OUT_OF_RANGE(ch)) {
#endif
	int info = GetUniCharInfo(ch);
	int mode = GetCaseType(info);

	if (mode & 0x1) {
	    /*
	     * Subtract or add one depending on the original case.
	     */

	    if (mode != 0x7) {
		ch += ((mode & 0x4) ? -1 : 1);
	    }
	} else if (mode == 0x4) {
	    ch -= GetDelta(info);
	}
#if TCL_UTF_MAX > 3
    }
    /* Clear away extension bits, if any */
    ch &= 0x1FFFFF;
#endif
    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharLen --







<
<
<
|
|

|
|
|
|

|
|
|
|
|
|
<
<
<
<
<







1258
1259
1260
1261
1262
1263
1264



1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278





1279
1280
1281
1282
1283
1284
1285
 *----------------------------------------------------------------------
 */

Tcl_UniChar
Tcl_UniCharToTitle(
    int ch)			/* Unicode character to convert. */
{



    int info = GetUniCharInfo(ch);
    int mode = GetCaseType(info);

    if (mode & 0x1) {
	/*
	 * Subtract or add one depending on the original case.
	 */

	if (mode != 0x7) {
	    ch += ((mode & 0x4) ? -1 : 1);
	}
    } else if (mode == 0x4) {
	ch -= GetDelta(info);
    }





    return (Tcl_UniChar) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharLen --
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharLen(
    const Tcl_UniChar *uniStr)	/* Unicode string to find length of. */
{
    int len = 0;

    while (*uniStr != '\0') {
	len++;
	uniStr++;
    }







|







1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharLen(
    CONST Tcl_UniChar *uniStr)	/* Unicode string to find length of. */
{
    int len = 0;

    while (*uniStr != '\0') {
	len++;
	uniStr++;
    }
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcmp(
    const Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    const Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    unsigned long numChars)	/* Number of unichars to compare. */
{
#ifdef WORDS_BIGENDIAN
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */








|
|







1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcmp(
    CONST Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    CONST Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    unsigned long numChars)	/* Number of unichars to compare. */
{
#ifdef WORDS_BIGENDIAN
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */

1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcasecmp(
    const Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    const Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    unsigned long numChars)	/* Number of unichars to compare. */
{
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);








|
|







1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcasecmp(
    CONST Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    CONST Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    unsigned long numChars)	/* Number of unichars to compare. */
{
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);

1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsAlnum(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return (((ALPHA_BITS | DIGIT_BITS) >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsAlpha --







<
<
<
<
<







1406
1407
1408
1409
1410
1411
1412





1413
1414
1415
1416
1417
1418
1419
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsAlnum(
    int ch)			/* Unicode character to test. */
{





    return (((ALPHA_BITS | DIGIT_BITS) >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsAlpha --
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsAlpha(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return ((ALPHA_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsControl --







<
<
<
<
<







1429
1430
1431
1432
1433
1434
1435





1436
1437
1438
1439
1440
1441
1442
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsAlpha(
    int ch)			/* Unicode character to test. */
{





    return ((ALPHA_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsControl --
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsControl(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	/* Clear away extension bits, if any */
	ch &= 0x1FFFFF;
	if ((ch == 0xE0001) || ((ch >= 0xE0020) && (ch <= 0xE007F))) {
	    return 1;
	}
	if ((ch >= 0xF0000) && ((ch & 0xFFFF) <= 0xFFFD)) {
	    return 1;
	}
	return 0;
    }
#endif
    return ((CONTROL_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsDigit --







<
<
<
<
<
<
<
<
<
<
<
<
<







1452
1453
1454
1455
1456
1457
1458













1459
1460
1461
1462
1463
1464
1465
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsControl(
    int ch)			/* Unicode character to test. */
{













    return ((CONTROL_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsDigit --
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsDigit(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return (GetCategory(ch) == DECIMAL_DIGIT_NUMBER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsGraph --







<
<
<
<
<







1475
1476
1477
1478
1479
1480
1481





1482
1483
1484
1485
1486
1487
1488
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsDigit(
    int ch)			/* Unicode character to test. */
{





    return (GetCategory(ch) == DECIMAL_DIGIT_NUMBER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsGraph --
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsGraph(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return ((unsigned)((ch & 0x1FFFFF) - 0xE0100) <= 0xEF);
    }
#endif
    return ((GRAPH_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsLower --







<
<
<
<
<







1498
1499
1500
1501
1502
1503
1504





1505
1506
1507
1508
1509
1510
1511
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsGraph(
    int ch)			/* Unicode character to test. */
{





    return ((GRAPH_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsLower --
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsLower(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return (GetCategory(ch) == LOWERCASE_LETTER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsPrint --







<
<
<
<
<







1521
1522
1523
1524
1525
1526
1527





1528
1529
1530
1531
1532
1533
1534
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsLower(
    int ch)			/* Unicode character to test. */
{





    return (GetCategory(ch) == LOWERCASE_LETTER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsPrint --
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsPrint(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return ((unsigned)((ch & 0x1FFFFF) - 0xE0100) <= 0xEF);
    }
#endif
    return (((GRAPH_BITS|SPACE_BITS) >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsPunct --







<
<
<
<
<







1544
1545
1546
1547
1548
1549
1550





1551
1552
1553
1554
1555
1556
1557
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsPrint(
    int ch)			/* Unicode character to test. */
{





    return (((GRAPH_BITS|SPACE_BITS) >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsPunct --
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsPunct(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return ((PUNCT_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsSpace --







<
<
<
<
<







1567
1568
1569
1570
1571
1572
1573





1574
1575
1576
1577
1578
1579
1580
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsPunct(
    int ch)			/* Unicode character to test. */
{





    return ((PUNCT_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsSpace --
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsSpace(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    /* Ignore upper 11 bits. */
    ch &= 0x1FFFFF;
#else
    /* Ignore upper 16 bits. */
    ch &= 0xFFFF;
#endif

    /*
     * If the character is within the first 127 characters, just use the
     * standard C function, otherwise consult the Unicode table.
     */

    if (ch < 0x80) {
	return TclIsSpaceProcM((char) ch);
#if TCL_UTF_MAX > 3
    } else if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
#endif
    } else if (ch == 0x180E || ch == 0x202F) {
	return 1;
    } else {
	return ((SPACE_BITS >> GetCategory(ch)) & 1);
    }
}

/*







<
<
<
<
<
<
<
<





|
|
<
<
<
<
|







1590
1591
1592
1593
1594
1595
1596








1597
1598
1599
1600
1601
1602
1603




1604
1605
1606
1607
1608
1609
1610
1611
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsSpace(
    int ch)			/* Unicode character to test. */
{








    /*
     * If the character is within the first 127 characters, just use the
     * standard C function, otherwise consult the Unicode table.
     */

    if (((Tcl_UniChar) ch) < ((Tcl_UniChar) 0x80)) {
	return TclIsSpaceProc((char) ch);




    } else if ((Tcl_UniChar) ch == 0x180E || (Tcl_UniChar) ch == 0x202F) {
	return 1;
    } else {
	return ((SPACE_BITS >> GetCategory(ch)) & 1);
    }
}

/*
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsUpper(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return (GetCategory(ch) == UPPERCASE_LETTER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsWordChar --







<
<
<
<
<







1624
1625
1626
1627
1628
1629
1630





1631
1632
1633
1634
1635
1636
1637
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsUpper(
    int ch)			/* Unicode character to test. */
{





    return (GetCategory(ch) == UPPERCASE_LETTER);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharIsWordChar --
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsWordChar(
    int ch)			/* Unicode character to test. */
{
#if TCL_UTF_MAX > 3
    if (UNICODE_OUT_OF_RANGE(ch)) {
	return 0;
    }
#endif
    return ((WORD_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharCaseMatch --







<
<
<
<
<







1647
1648
1649
1650
1651
1652
1653





1654
1655
1656
1657
1658
1659
1660
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharIsWordChar(
    int ch)			/* Unicode character to test. */
{





    return ((WORD_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharCaseMatch --
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharCaseMatch(
    const Tcl_UniChar *uniStr,	/* Unicode String. */
    const Tcl_UniChar *uniPattern,
				/* Pattern, which may contain special
				 * characters. */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    Tcl_UniChar ch1, p;

    while (1) {







|
|







1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharCaseMatch(
    CONST Tcl_UniChar *uniStr,	/* Unicode String. */
    CONST Tcl_UniChar *uniPattern,
				/* Pattern, which may contain special
				 * characters. */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    Tcl_UniChar ch1, p;

    while (1) {
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharMatch(
    const Tcl_UniChar *string,	/* Unicode String. */
    int strLen,			/* Length of String */
    const Tcl_UniChar *pattern,	/* Pattern, which may contain special
				 * characters. */
    int ptnLen,			/* Length of Pattern */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    const Tcl_UniChar *stringEnd, *patternEnd;
    Tcl_UniChar p;

    stringEnd = string + strLen;
    patternEnd = pattern + ptnLen;

    while (1) {
	/*







|

|




|







1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharMatch(
    CONST Tcl_UniChar *string,	/* Unicode String. */
    int strLen,			/* Length of String */
    CONST Tcl_UniChar *pattern,	/* Pattern, which may contain special
				 * characters. */
    int ptnLen,			/* Length of Pattern */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    CONST Tcl_UniChar *stringEnd, *patternEnd;
    Tcl_UniChar p;

    stringEnd = string + strLen;
    patternEnd = pattern + ptnLen;

    while (1) {
	/*

Changes to generic/tclUtil.c.

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

    if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
	/* Empty string case - quick exit */
	goto done;
    }

    /* No list element before leading white space */
    count += 1 - TclIsSpaceProcM(*bytes);

    /* Count white space runs as potential element separators */
    while (numBytes) {
	if ((numBytes == -1) && (*bytes == '\0')) {
	    break;
	}
	if (TclIsSpaceProcM(*bytes)) {
	    /* Space run started; bump count */
	    count++;
	    do {
		bytes++;
		numBytes -= (numBytes != -1);
	    } while (numBytes && TclIsSpaceProcM(*bytes));
	    if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
		break;
	    }
	    /* (*bytes) is non-space; return to counting state */
	}
	bytes++;
	numBytes -= (numBytes != -1);
    }

    /* No list element following trailing white space */
    count -= TclIsSpaceProcM(bytes[-1]);

    done:
    if (endPtr) {
	*endPtr = bytes;
    }
    return count;
}







|






|





|










|







392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

    if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
	/* Empty string case - quick exit */
	goto done;
    }

    /* No list element before leading white space */
    count += 1 - TclIsSpaceProc(*bytes);

    /* Count white space runs as potential element separators */
    while (numBytes) {
	if ((numBytes == -1) && (*bytes == '\0')) {
	    break;
	}
	if (TclIsSpaceProc(*bytes)) {
	    /* Space run started; bump count */
	    count++;
	    do {
		bytes++;
		numBytes -= (numBytes != -1);
	    } while (numBytes && TclIsSpaceProc(*bytes));
	    if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
		break;
	    }
	    /* (*bytes) is non-space; return to counting state */
	}
	bytes++;
	numBytes -= (numBytes != -1);
    }

    /* No list element following trailing white space */
    count -= TclIsSpaceProc(bytes[-1]);

    done:
    if (endPtr) {
	*endPtr = bytes;
    }
    return count;
}
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    /*
     * Skim off leading white space and check for an opening brace or quote.
     * We treat embedded NULLs in the list as bytes belonging to a list
     * element.
     */

    limit = (list + listLength);
    while ((p < limit) && (TclIsSpaceProcM(*p))) {
	p++;
    }
    if (p == limit) {		/* no element found */
	elemStart = limit;
	goto done;
    }








|







504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    /*
     * Skim off leading white space and check for an opening brace or quote.
     * We treat embedded NULLs in the list as bytes belonging to a list
     * element.
     */

    limit = (list + listLength);
    while ((p < limit) && (TclIsSpaceProc(*p))) {
	p++;
    }
    if (p == limit) {		/* no element found */
	elemStart = limit;
	goto done;
    }

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

	case '}':
	    if (openBraces > 1) {
		openBraces--;
	    } else if (openBraces == 1) {
		size = (p - elemStart);
		p++;
		if ((p >= limit) || TclIsSpaceProcM(*p)) {
		    goto done;
		}

		/*
		 * Garbage after the closing brace; return an error.
		 */

		if (interp != NULL) {
		    p2 = p;
		    while ((p2 < limit) && (!TclIsSpaceProcM(*p2))
			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "list element in braces followed by \"%.*s\" "
			    "instead of space", (int) (p2-p), p));
		}







|









|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

	case '}':
	    if (openBraces > 1) {
		openBraces--;
	    } else if (openBraces == 1) {
		size = (p - elemStart);
		p++;
		if ((p >= limit) || TclIsSpaceProc(*p)) {
		    goto done;
		}

		/*
		 * Garbage after the closing brace; return an error.
		 */

		if (interp != NULL) {
		    p2 = p;
		    while ((p2 < limit) && (!TclIsSpaceProc(*p2))
			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "list element in braces followed by \"%.*s\" "
			    "instead of space", (int) (p2-p), p));
		}
590
591
592
593
594
595
596

















597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
		 */
		literal = 0;
	    }
	    TclParseBackslash(p, limit - p, &numChars, NULL);
	    p += (numChars - 1);
	    break;


















	    /*
	     * Double-quote: if element is in quotes then terminate it.
	     */

	case '"':
	    if (inQuotes) {
		size = (p - elemStart);
		p++;
		if ((p >= limit) || TclIsSpaceProcM(*p)) {
		    goto done;
		}

		/*
		 * Garbage after the closing quote; return an error.
		 */

		if (interp != NULL) {
		    p2 = p;
		    while ((p2 < limit) && (!TclIsSpaceProcM(*p2))
			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "list element in quotes followed by \"%.*s\" "
			    "instead of space", (int) (p2-p), p));
		}
		return TCL_ERROR;
	    }
	    break;

	default:
	    if (TclIsSpaceProcM(*p)) {
		/*
		 * Space: ignore if element is in braces or quotes;
		 * otherwise terminate element.
		 */
		if ((openBraces == 0) && !inQuotes) {
		    size = (p - elemStart);
		    goto done;
		}
	    }
	    break;

	}
	p++;
    }

    /*
     * End of list: terminate element.
     */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|









|










<
<
<
<
<
<
<
<
<
<
<
<
<
<







590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642














643
644
645
646
647
648
649
		 */
		literal = 0;
	    }
	    TclParseBackslash(p, limit - p, &numChars, NULL);
	    p += (numChars - 1);
	    break;

	    /*
	     * Space: ignore if element is in braces or quotes; otherwise
	     * terminate element.
	     */

	case ' ':
	case '\f':
	case '\n':
	case '\r':
	case '\t':
	case '\v':
	    if ((openBraces == 0) && !inQuotes) {
		size = (p - elemStart);
		goto done;
	    }
	    break;

	    /*
	     * Double-quote: if element is in quotes then terminate it.
	     */

	case '"':
	    if (inQuotes) {
		size = (p - elemStart);
		p++;
		if ((p >= limit) || TclIsSpaceProc(*p)) {
		    goto done;
		}

		/*
		 * Garbage after the closing quote; return an error.
		 */

		if (interp != NULL) {
		    p2 = p;
		    while ((p2 < limit) && (!TclIsSpaceProc(*p2))
			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "list element in quotes followed by \"%.*s\" "
			    "instead of space", (int) (p2-p), p));
		}
		return TCL_ERROR;
	    }
	    break;














	}
	p++;
    }

    /*
     * End of list: terminate element.
     */
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
	    }
	    return TCL_ERROR;
	}
	size = (p - elemStart);
    }

  done:
    while ((p < limit) && (TclIsSpaceProcM(*p))) {
	p++;
    }
    *elementPtr = elemStart;
    *nextPtr = p;
    if (sizePtr != 0) {
	*sizePtr = size;
    }







|







662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
	    }
	    return TCL_ERROR;
	}
	size = (p - elemStart);
    }

  done:
    while ((p < limit) && (TclIsSpaceProc(*p))) {
	p++;
    }
    *elementPtr = elemStart;
    *nextPtr = p;
    if (sizePtr != 0) {
	*sizePtr = size;
    }
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

    if ((p == NULL) || (length == 0) || ((*p == '\0') && (length == -1))) {
	/* Empty string element must be brace quoted. */
	*flagPtr = CONVERT_BRACE;
	return 2;
    }

#if COMPAT
    /*
     * We have an established history in TclConvertElement() when quoting
     * because of a leading hash character to force what would be the
     * CONVERT_MASK mode into the CONVERT_BRACE mode. That is, we format
     * the element #{a"b} like this:
     *			{#{a"b}}
     * and not like this:
     *			\#{a\"b}
     * This is inconsistent with [list x{a"b}], but we will not change that now.
     * Set that preference here so that we compute a tight size requirement.
     */
    if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
	preferBrace = 1;
    }
#endif

    if ((*p == '{') || (*p == '"')) {
	/*
	 * Must escape or protect so leading character of value is not
	 * misinterpreted as list element delimiting syntax.
	 */
	forbidNone = 1;
#if COMPAT







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







948
949
950
951
952
953
954

















955
956
957
958
959
960
961

    if ((p == NULL) || (length == 0) || ((*p == '\0') && (length == -1))) {
	/* Empty string element must be brace quoted. */
	*flagPtr = CONVERT_BRACE;
	return 2;
    }


















    if ((*p == '{') || (*p == '"')) {
	/*
	 * Must escape or protect so leading character of value is not
	 * misinterpreted as list element delimiting syntax.
	 */
	forbidNone = 1;
#if COMPAT
1006
1007
1008
1009
1010
1011
1012






1013
1014
1015
1016
1017
1018
1019
	    break;
#else
	    /* FLOW THROUGH */
#endif
	case '[':
	case '$':
	case ';':






	    forbidNone = 1;
	    extra++;		/* Escape sequences all one byte longer. */
#if COMPAT
	    preferBrace = 1;
#endif
	    break;
	case '\\':







>
>
>
>
>
>







992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
	    break;
#else
	    /* FLOW THROUGH */
#endif
	case '[':
	case '$':
	case ';':
	case ' ':
	case '\f':
	case '\n':
	case '\r':
	case '\t':
	case '\v':
	    forbidNone = 1;
	    extra++;		/* Escape sequences all one byte longer. */
#if COMPAT
	    preferBrace = 1;
#endif
	    break;
	case '\\':
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
#endif
	    break;
	case '\0':
	    if (length == -1) {
		goto endOfString;
	    }
	    /* TODO: Panic on improper encoding? */
	    break;
	default:
	    if (TclIsSpaceProcM(*p)) {
		forbidNone = 1;
		extra++;	/* Escape sequences all one byte longer. */
#if COMPAT
		preferBrace = 1;
#endif
	    }
	    break;
	}
	length -= (length > 0);
	p++;
    }

    endOfString:







<
<
<
<
<
<
<
<
<







1034
1035
1036
1037
1038
1039
1040









1041
1042
1043
1044
1045
1046
1047
#endif
	    break;
	case '\0':
	    if (length == -1) {
		goto endOfString;
	    }
	    /* TODO: Panic on improper encoding? */









	    break;
	}
	length -= (length > 0);
	p++;
    }

    endOfString:
1512
1513
1514
1515
1516
1517
1518




































1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582
1583
1584































1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
    TclUtfToUniChar(buf, &ch);
    return (char) ch;
}

/*
 *----------------------------------------------------------------------
 *




































 * TclTrimRight --
 *	Takes two counted strings in the Tcl encoding.  Conceptually
 *	finds the sub string (offset) to trim from the right side of the
 *	first string all characters found in the second string.
 *
 * Results:
 *	The number of bytes to be removed from the end of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclTrimRight(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (trim[numTrim] == '\0'). */
{
    const char *pp, *p = bytes + numBytes;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    /* Outer loop: iterate over string to be trimmed */
    do {
	Tcl_UniChar ch1;
	const char *q = trim;
	int pInc = 0, bytesLeft = numTrim;

	pp = TclUtfPrev(p, bytes);
	do {
	    pp += pInc;
 	    pInc = TclUtfToUniChar(pp, &ch1);
	} while (pp + pInc < p);

	/* Inner loop: scan trim string for match to current character */
	do {
	    Tcl_UniChar ch2;
	    int qInc = TclUtfToUniChar(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;
	} while (bytesLeft);

	if (bytesLeft == 0) {
	    /* No match; trim task done; *p is last non-trimmed char */

	    break;
	}
	p = pp;
    } while (p > bytes);

    return numBytes - (p - bytes);
}
































/*
 *----------------------------------------------------------------------
 *
 * TclTrimLeft --
 *	Takes two counted strings in the Tcl encoding.  Conceptually
 *	finds the sub string (offset) to trim from the left side of the
 *	first string all characters found in the second string.
 *
 * Results:
 *	The number of bytes to be removed from the start of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclTrimLeft(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (trim[numTrim] == '\0'). */
{
    const char *p = bytes;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    /* Outer loop: iterate over string to be trimmed */
    do {
	Tcl_UniChar ch1;
	int pInc = TclUtfToUniChar(p, &ch1);
	const char *q = trim;
	int bytesLeft = numTrim;








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|


<
<


<
<

|
|
<
<
<
<





|

|
<
<
|
<
















>


<




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|
|


<
<


<
<



<
<
<
<
<







1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555


1556
1557


1558
1559
1560




1561
1562
1563
1564
1565
1566
1567
1568


1569

1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645


1646
1647


1648
1649
1650





1651
1652
1653
1654
1655
1656
1657
    TclUtfToUniChar(buf, &ch);
    return (char) ch;
}

/*
 *----------------------------------------------------------------------
 *
 * UtfWellFormedEnd --
 *	Checks the end of utf string is malformed, if yes - wraps bytes
 *	to the given buffer (as well-formed NTS string).  The buffer
 *	argument should be initialized by the caller and ready to use.
 *
 * Results:
 *	The bytes with well-formed end of the string.
 *
 * Side effects:
 *	Buffer (DString) may be allocated, so must be released.
 *
 *----------------------------------------------------------------------
 */

static inline const char*
UtfWellFormedEnd(
    Tcl_DString *buffer,	/* Buffer used to hold well-formed string. */
    CONST char *bytes,		/* Pointer to the beginning of the string. */
    int length)			/* Length of the string. */
{
    CONST char *l = bytes + length;
    CONST char *p = Tcl_UtfPrev(l, bytes);

    if (Tcl_UtfCharComplete(p, l - p)) {
	return bytes;
    }
    /* 
     * Malformed utf-8 end, be sure we've NTS to safe compare of end-character,
     * avoid segfault by access violation out of range.
     */
    Tcl_DStringAppend(buffer, bytes, length);
    return Tcl_DStringValue(buffer);
}
/*
 *----------------------------------------------------------------------
 *
 * TclTrimRight --
 *	Takes two counted strings in the Tcl encoding.  Conceptually
 *	finds the sub string (offset) to trim from the right side of the
 *	first string all characters found in the second string.
 *
 * Results:
 *	The number of bytes to be removed from the end of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline int
TrimRight(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */


    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */


{
    const char *p = bytes + numBytes;
    int pInc;





    /* Outer loop: iterate over string to be trimmed */
    do {
	Tcl_UniChar ch1;
	const char *q = trim;
	int bytesLeft = numTrim;

	p = Tcl_UtfPrev(p, bytes);


 	pInc = TclUtfToUniChar(p, &ch1);


	/* Inner loop: scan trim string for match to current character */
	do {
	    Tcl_UniChar ch2;
	    int qInc = TclUtfToUniChar(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;
	} while (bytesLeft);

	if (bytesLeft == 0) {
	    /* No match; trim task done; *p is last non-trimmed char */
	    p += pInc;
	    break;
	}

    } while (p > bytes);

    return numBytes - (p - bytes);
}

int
TclTrimRight(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */
    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */
{
    int res;
    Tcl_DString bytesBuf, trimBuf;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    Tcl_DStringInit(&bytesBuf);
    Tcl_DStringInit(&trimBuf);
    bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
    trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);

    res = TrimRight(bytes, numBytes, trim, numTrim);
    if (res > numBytes) {
	res = numBytes;
    }

    Tcl_DStringFree(&bytesBuf);
    Tcl_DStringFree(&trimBuf);

    return res;
}

/*
 *----------------------------------------------------------------------
 *
 * TclTrimLeft --
 *	Takes two counted strings in the Tcl encoding.  Conceptually
 *	finds the sub string (offset) to trim from the left side of the
 *	first string all characters found in the second string.
 *
 * Results:
 *	The number of bytes to be removed from the start of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline int
TrimLeft(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */


    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */


{
    const char *p = bytes;






    /* Outer loop: iterate over string to be trimmed */
    do {
	Tcl_UniChar ch1;
	int pInc = TclUtfToUniChar(p, &ch1);
	const char *q = trim;
	int bytesLeft = numTrim;

1645
1646
1647
1648
1649
1650
1651































1652
1653
1654
1655
1656
1657
1658

	p += pInc;
	numBytes -= pInc;
    } while (numBytes > 0);

    return p - bytes;
}
































/*
 *----------------------------------------------------------------------
 *
 * TclTrim --
 *	Finds the sub string (offset) to trim from both sides of the
 *	first string all characters found in the second string.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719

	p += pInc;
	numBytes -= pInc;
    } while (numBytes > 0);

    return p - bytes;
}

int
TclTrimLeft(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */
    const char *trim,	/* String of trim characters... */
    int numTrim)	/* ...and its length in bytes */
{
    int res;
    Tcl_DString bytesBuf, trimBuf;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    Tcl_DStringInit(&bytesBuf);
    Tcl_DStringInit(&trimBuf);
    bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
    trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);

    res = TrimLeft(bytes, numBytes, trim, numTrim);
    if (res > numBytes) {
	res = numBytes;
    }

    Tcl_DStringFree(&bytesBuf);
    Tcl_DStringFree(&trimBuf);

    return res;
}

/*
 *----------------------------------------------------------------------
 *
 * TclTrim --
 *	Finds the sub string (offset) to trim from both sides of the
 *	first string all characters found in the second string.
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681

1682

1683
1684

1685
1686


1687
1688
1689
1690
1691
1692
1693
1694
1695
1696


1697
1698
1699
1700


1701
1702
1703


1704
1705
1706
1707
1708
1709
1710
1711
 *----------------------------------------------------------------------
 */

int
TclTrim(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    int numTrim,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (trim[numTrim] == '\0'). */
    int *trimRightPtr)	/* Offset from the end of the string. */
{
    int trimLeft = 0, trimRight = 0;



    /* Empty strings -> nothing to do */
    if ((numBytes > 0) && (numTrim > 0)) {


	/* When bytes is NUL-terminated, returns 0 <= trimLeft <= numBytes */


	trimLeft = TclTrimLeft(bytes, numBytes, trim, numTrim);
	numBytes -= trimLeft;

	/* If we did not trim the whole string, it starts with a character
	 * that we will not trim. Skip over it. */
	if (numBytes > 0) {
	    const char *first = bytes + trimLeft;
	    bytes = TclUtfNext(first);
	    numBytes -= (bytes - first);



	    if (numBytes > 0) {
		/* When bytes is NUL-terminated, returns
		 * 0 <= trimRight <= numBytes */
		trimRight = TclTrimRight(bytes, numBytes, trim, numTrim);


	    }
	}
    }


    *trimRightPtr = trimRight;
    return trimLeft;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Concat --







<
<


<
<
|

|
>

>

|
>
|
|
>
>
|
|

<
<
|
|
<
|
|
>
>
|
<
|
|
>
>
|
|
|
>
>
|







1727
1728
1729
1730
1731
1732
1733


1734
1735


1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751


1752
1753

1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
 *----------------------------------------------------------------------
 */

int
TclTrim(
    const char *bytes,	/* String to be trimmed... */
    int numBytes,	/* ...and its length in bytes */


    const char *trim,	/* String of trim characters... */
    int numTrim,	/* ...and its length in bytes */


    int *trimRight)		/* Offset from the end of the string. */
{
    int trimLeft;
    Tcl_DString bytesBuf, trimBuf;

    *trimRight = 0;
    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    Tcl_DStringInit(&bytesBuf);
    Tcl_DStringInit(&trimBuf);
    bytes = UtfWellFormedEnd(&bytesBuf, bytes, numBytes);
    trim = UtfWellFormedEnd(&trimBuf, trim, numTrim);



    trimLeft = TrimLeft(bytes, numBytes, trim, numTrim);
    if (trimLeft > numBytes) {

	trimLeft = numBytes;
    }
    numBytes -= trimLeft;
    /* have to trim yet (first char was already verified within TrimLeft) */
    if (numBytes > 1) {

	bytes += trimLeft;
	*trimRight = TrimRight(bytes, numBytes, trim, numTrim);
	if (*trimRight > numBytes) {
	    *trimRight = numBytes;
	}
    }

    Tcl_DStringFree(&bytesBuf);
    Tcl_DStringFree(&trimBuf);

    return trimLeft;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Concat --
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
 *	Memory is allocated for the result; the caller is responsible for
 *	freeing the memory.
 *
 *----------------------------------------------------------------------
 */

/* The whitespace characters trimmed during [concat] operations */
/* TODO: Find a reasonable way to guarantee in sync with TclIsSpaceProc() */
#define CONCAT_WS " \f\v\r\t\n"
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)

char *
Tcl_Concat(
    int argc,			/* Number of strings to concatenate. */
    CONST char * CONST *argv)	/* Array of strings to concatenate. */







<







1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
 *	Memory is allocated for the result; the caller is responsible for
 *	freeing the memory.
 *
 *----------------------------------------------------------------------
 */

/* The whitespace characters trimmed during [concat] operations */

#define CONCAT_WS " \f\v\r\t\n"
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)

char *
Tcl_Concat(
    int argc,			/* Number of strings to concatenate. */
    CONST char * CONST *argv)	/* Array of strings to concatenate. */
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
	    objPtr = objv[i];
	    if (objPtr->bytes && objPtr->length == 0) {
		continue;
	    }
	    TclListObjGetElements(NULL, objPtr, &listc, &listv);
	    if (listc) {
		if (resPtr) {
		    if (Tcl_GetString(listv[0])[0] == '#'
			    || TCL_OK != Tcl_ListObjReplace(NULL, resPtr,
			    INT_MAX, 0, listc, listv)) {
			/* Abandon ship! */
			Tcl_DecrRefCount(resPtr);
			goto slow;
		    }
		} else {
		    resPtr = TclListObjCopy(NULL, objPtr);







<
|







1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1932
	    objPtr = objv[i];
	    if (objPtr->bytes && objPtr->length == 0) {
		continue;
	    }
	    TclListObjGetElements(NULL, objPtr, &listc, &listv);
	    if (listc) {
		if (resPtr) {

		    if (TCL_OK != Tcl_ListObjReplace(NULL, resPtr,
			    INT_MAX, 0, listc, listv)) {
			/* Abandon ship! */
			Tcl_DecrRefCount(resPtr);
			goto slow;
		    }
		} else {
		    resPtr = TclListObjCopy(NULL, objPtr);
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
Tcl_StringCaseMatch(
    CONST char *str,		/* String. */
    CONST char *pattern,	/* Pattern, which may contain special
				 * characters. */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    int p, charLen;

    Tcl_UniChar ch1, ch2;

    while (1) {
	p = *pattern;

	/*
	 * See if we're at the end of both the pattern and the string. If so,







>







2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
Tcl_StringCaseMatch(
    CONST char *str,		/* String. */
    CONST char *pattern,	/* Pattern, which may contain special
				 * characters. */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    int p, charLen;
    CONST char *pstart = pattern;
    Tcl_UniChar ch1, ch2;

    while (1) {
	p = *pattern;

	/*
	 * See if we're at the end of both the pattern and the string. If so,
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161

			break;
		    }
		} else if (startChar == ch1) {
		    break;
		}
	    }
	    /* If we reach here, we matched. Need to move past closing ] */
	    while (*pattern != ']') {
		if (*pattern == '\0') {
		    /* We ran out of pattern after matching something in
		     * (unclosed!) brackets. So long as we ran out of string
		     * at the same time, we have a match. Otherwise, not. */
		    return (*str == '\0');
		}
		pattern++;
	    }
	    pattern++;
	    continue;
	}








<


|
<
<
|







2204
2205
2206
2207
2208
2209
2210

2211
2212
2213


2214
2215
2216
2217
2218
2219
2220
2221

			break;
		    }
		} else if (startChar == ch1) {
		    break;
		}
	    }

	    while (*pattern != ']') {
		if (*pattern == '\0') {
		    pattern = Tcl_UtfPrev(pattern, pstart);


		    break;
		}
		pattern++;
	    }
	    pattern++;
	    continue;
	}

2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
Tcl_DStringAppendElement(
    Tcl_DString *dsPtr,		/* Structure describing dynamic string. */
    CONST char *element)	/* String to append. Must be
				 * null-terminated. */
{
    char *dst = dsPtr->string + dsPtr->length;
    int needSpace = TclNeedSpace(dsPtr->string, dst);
    int flags = 0, quoteHash = 1, newSize;

    if (needSpace) {
	/*
	 * If we need a space to separate the new element from something
	 * already ending the string, we're not appending the first element
	 * of any list, so we need not quote any leading hash character.
	 */
	quoteHash = 0;
    } else {
	/*
	 * We don't need a space, maybe because there's some already there.
	 * Checking whether we might be appending a first element is a bit
	 * more involved.
	 *
	 * Backtrack over all whitespace.
	 */
	while ((--dst >= dsPtr->string) && TclIsSpaceProcM(*dst)) {
	}

	/* Call again without whitespace to confound things. */
	quoteHash = !TclNeedSpace(dsPtr->string, dst+1);
    }
    if (!quoteHash) {
	flags |= TCL_DONT_QUOTE_HASH;
    }
    newSize = dsPtr->length + needSpace + TclScanElement(element, -1, &flags);
    if (!quoteHash) {
	flags |= TCL_DONT_QUOTE_HASH;
    }

    /*
     * Allocate a larger buffer for the string if the current one isn't large
     * enough. Allocate extra space in the new buffer so that there will be
     * room to grow before we have to allocate again. SPECIAL NOTE: must use
     * memcpy, not strcpy, to copy the string to a larger buffer, since there
     * may be embedded NULLs in the string in some cases.







<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<







2608
2609
2610
2611
2612
2613
2614

2615

















2616






2617



2618
2619
2620
2621
2622
2623
2624
Tcl_DStringAppendElement(
    Tcl_DString *dsPtr,		/* Structure describing dynamic string. */
    CONST char *element)	/* String to append. Must be
				 * null-terminated. */
{
    char *dst = dsPtr->string + dsPtr->length;
    int needSpace = TclNeedSpace(dsPtr->string, dst);

    int flags = needSpace ? TCL_DONT_QUOTE_HASH : 0;

















    int newSize = dsPtr->length + needSpace






	    + TclScanElement(element, -1, &flags);




    /*
     * Allocate a larger buffer for the string if the current one isn't large
     * enough. Allocate extra space in the new buffer so that there will be
     * room to grow before we have to allocate again. SPECIAL NOTE: must use
     * memcpy, not strcpy, to copy the string to a larger buffer, since there
     * may be embedded NULLs in the string in some cases.
2610
2611
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629





2630


2631
2632
2633
2634
2635
2636
2637
	    dsPtr->string = (char *) ckrealloc((void *) dsPtr->string,
		    (size_t) dsPtr->spaceAvl);

	    if (offset >= 0) {
		element = dsPtr->string + offset;
	    }
	}
    }
    dst = dsPtr->string + dsPtr->length;


    /*
     * Convert the new string to a list element and copy it into the buffer at
     * the end, with a space, if needed.
     */

    if (needSpace) {
	*dst = ' ';
	dst++;
	dsPtr->length++;
    }








    dsPtr->length += TclConvertElement(element, -1, dst, flags);
    dsPtr->string[dsPtr->length] = '\0';
    return dsPtr->string;
}

/*
 *----------------------------------------------------------------------







<
|
>










|
>
>
>
>
>

>
>







2643
2644
2645
2646
2647
2648
2649

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
	    dsPtr->string = (char *) ckrealloc((void *) dsPtr->string,
		    (size_t) dsPtr->spaceAvl);

	    if (offset >= 0) {
		element = dsPtr->string + offset;
	    }
	}

	dst = dsPtr->string + dsPtr->length;
    }

    /*
     * Convert the new string to a list element and copy it into the buffer at
     * the end, with a space, if needed.
     */

    if (needSpace) {
	*dst = ' ';
	dst++;
	dsPtr->length++;

	/*
	 * If we need a space to separate this element from preceding stuff,
	 * then this element will not lead a list, and need not have it's
	 * leading '#' quoted.
	 */

	flags |= TCL_DONT_QUOTE_HASH;
    }
    dsPtr->length += TclConvertElement(element, -1, dst, flags);
    dsPtr->string[dsPtr->length] = '\0';
    return dsPtr->string;
}

/*
 *----------------------------------------------------------------------
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219








3220
3221
3222
3223
3224
3225
3226


3227



3228

3229
3230







3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
    CONST char *start,		/* First character in string. */
    CONST char *end)		/* End of string (place where space will be
				 * added, if appropriate). */
{
    /*
     * A space is needed unless either:
     * (a) we're at the start of the string, or
     *
     * (NOTE: This check is now absorbed into the loop below.)
     *

    if (end == start) {
	return 0;
    }

     *
     */

    /*
     * (b) we're at the start of a nested list-element, quoted with an open
     *	   curly brace; we can be nested arbitrarily deep, so long as the
     *	   first curly brace starts an element, so backtrack over open curly
     *	   braces that are trailing characters of the string; and
     *
     *  (NOTE: Every character our parser is looking for is a proper
     *  single-byte encoding of an ASCII value. It does not accept
     *  overlong encodings.  Given that, there's no benefit using
     *  Tcl_UtfPrev. If it would find what we seek, so would byte-by-byte
     *  backward scan. Save routine call overhead and risk of wrong
     *  results should the behavior of Tcl_UtfPrev change in unexpected ways.
     *	Reconsider this if we ever start treating non-ASCII Unicode
     *	characters as meaningful list syntax, expanded Unicode spaces as
     *	element separators, for example.)
     *

    end = Tcl_UtfPrev(end, start);
    while (*end == '{') {
        if (end == start) {
            return 0;
        }
        end = Tcl_UtfPrev(end, start);
    }

     *
     */

    while ((--end >= start) && (*end == '{')) {
    }
    if (end < start) {
        return 0;
    }

    /*
     * (c) the trailing character of the string is already a list-element
     *	   separator, Use the same testing routine as TclFindElement to
     *	   enforce consistency.








     */

    if (TclIsSpaceProcM(*end)) {
	int result = 0;

	/*
	 * Trailing whitespace might be part of a backslash escape


	 * sequence. Handle that possibility.



	 */


	while ((--end >= start) && (*end == '\\')) {







	    result = !result;
	}
	return result;
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *







|
<
<





<
<
<





|
<
<
<
<
<
<
<
<
<
|
<


|
|
|
|
<
<
<
<
<
<
<
<
<




|
|
>
>
>
>
>
>
>
>


<
<
|

<
>
>
|
>
>
>

>
|
|
>
>
>
>
>
>
>
|

<







3204
3205
3206
3207
3208
3209
3210
3211


3212
3213
3214
3215
3216



3217
3218
3219
3220
3221
3222









3223

3224
3225
3226
3227
3228
3229









3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245


3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266

3267
3268
3269
3270
3271
3272
3273
    CONST char *start,		/* First character in string. */
    CONST char *end)		/* End of string (place where space will be
				 * added, if appropriate). */
{
    /*
     * A space is needed unless either:
     * (a) we're at the start of the string, or
     */



    if (end == start) {
	return 0;
    }




    /*
     * (b) we're at the start of a nested list-element, quoted with an open
     *	   curly brace; we can be nested arbitrarily deep, so long as the
     *	   first curly brace starts an element, so backtrack over open curly
     *	   braces that are trailing characters of the string; and
     */











    end = Tcl_UtfPrev(end, start);
    while (*end == '{') {
	if (end == start) {
	    return 0;
	}
	end = Tcl_UtfPrev(end, start);









    }

    /*
     * (c) the trailing character of the string is already a list-element
     *	   separator (according to TclFindElement); that is, one of these
     *	   characters:
     *		\u0009	\t	TAB
     *		\u000A	\n	NEWLINE
     *		\u000B	\v	VERTICAL TAB
     *		\u000C	\f	FORM FEED
     *		\u000D	\r	CARRIAGE RETURN
     *		\u0020		SPACE
     *	   with the condition that the penultimate character is not a
     *	   backslash.
     */



    if (*end > 0x20) {
	/*

	 * Performance tweak. All ASCII spaces are <= 0x20. So get a quick
	 * answer for most characters before comparing against all spaces in
	 * the switch below.
	 *
	 * NOTE: Remove this if other Unicode spaces ever get accepted as
	 * list-element separators.
	 */
	return 1;
    }
    switch (*end) {
    case ' ':
    case '\t':
    case '\n':
    case '\r':
    case '\v':
    case '\f':
	if ((end == start) || (end[-1] != '\\')) {
	    return 0;
	}

    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282











3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301

int
TclFormatInt(buffer, n)
    char *buffer;		/* Points to the storage into which the
				 * formatted characters are written. */
    long n;			/* The integer to format. */
{
    unsigned long intVal;
    int i;
    int numFormatted, j;
    static const char digits[] = "0123456789";

    /*
     * Check first whether "n" is zero.
     */

    if (n == 0) {
	buffer[0] = '0';
	buffer[1] = 0;
	return 1;
    }












    /*
     * Generate the characters of the result backwards in the buffer.
     */

    intVal = (n < 0 ? -(unsigned long)n : (unsigned long)n);
    i = 0;
    buffer[0] = '\0';
    do {
	i++;
	buffer[i] = digits[intVal % 10];
	intVal = intVal / 10;
    } while (intVal > 0);
    if (n < 0) {
	i++;
	buffer[i] = '-';
    }
    numFormatted = i;








|


|










>
>
>
>
>
>
>
>
>
>
>





|





|







3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345

int
TclFormatInt(buffer, n)
    char *buffer;		/* Points to the storage into which the
				 * formatted characters are written. */
    long n;			/* The integer to format. */
{
    long intVal;
    int i;
    int numFormatted, j;
    char *digits = "0123456789";

    /*
     * Check first whether "n" is zero.
     */

    if (n == 0) {
	buffer[0] = '0';
	buffer[1] = 0;
	return 1;
    }

    /*
     * Check whether "n" is the maximum negative value. This is
     * -2^(m-1) for an m-bit word, and has no positive equivalent;
     * negating it produces the same value.
     */

    intVal = -n;			/* [Bug 3390638] Workaround for*/
    if (n == -n || intVal == n) {	/* broken compiler optimizers. */
	return sprintf(buffer, "%ld", n);
    }

    /*
     * Generate the characters of the result backwards in the buffer.
     */

    intVal = (n < 0? -n : n);
    i = 0;
    buffer[0] = '\0';
    do {
	i++;
	buffer[i] = digits[intVal % 10];
	intVal = intVal/10;
    } while (intVal > 0);
    if (n < 0) {
	i++;
	buffer[i] = '-';
    }
    numFormatted = i;

3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393

    bytes = TclGetStringFromObj(objPtr, &length);

    /*
     * Leading whitespace is acceptable in an index.
     */

    while (length && TclIsSpaceProcM(*bytes)) {
	bytes++;
	length--;
    }

    if (TclParseNumber(NULL, NULL, NULL, bytes, length, (const char **)&opPtr,
	    TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
	int code, first, second;
	char savedOp = *opPtr;

	if ((savedOp != '+') && (savedOp != '-')) {
	    goto parseError;
	}
	if (TclIsSpaceProcM(opPtr[1])) {
	    goto parseError;
	}
	*opPtr = '\0';
	code = Tcl_GetInt(interp, bytes, &first);
	*opPtr = savedOp;
	if (code == TCL_ERROR) {
	    goto parseError;







|












|







3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437

    bytes = TclGetStringFromObj(objPtr, &length);

    /*
     * Leading whitespace is acceptable in an index.
     */

    while (length && TclIsSpaceProc(*bytes)) {
	bytes++;
	length--;
    }

    if (TclParseNumber(NULL, NULL, NULL, bytes, length, (const char **)&opPtr,
	    TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
	int code, first, second;
	char savedOp = *opPtr;

	if ((savedOp != '+') && (savedOp != '-')) {
	    goto parseError;
	}
	if (TclIsSpaceProc(opPtr[1])) {
	    goto parseError;
	}
	*opPtr = '\0';
	code = Tcl_GetInt(interp, bytes, &first);
	*opPtr = savedOp;
	if (code == TCL_ERROR) {
	    goto parseError;
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
	offset = 0;
    } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) {
	/*
	 * This is our limited string expression evaluator. Pass everything
	 * after "end-" to Tcl_GetInt, then reverse for offset.
	 */

	if (TclIsSpaceProcM(bytes[4])) {
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (bytes[3] == '-') {
	    offset = -offset;







|







3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
	offset = 0;
    } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) {
	/*
	 * This is our limited string expression evaluator. Pass everything
	 * after "end-" to Tcl_GetInt, then reverse for offset.
	 */

	if (TclIsSpaceProc(bytes[4])) {
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (bytes[3] == '-') {
	    offset = -offset;
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
    register CONST char *p = value;

    /*
     * A frequent mistake is invalid octal values due to an unwanted leading
     * zero. Try to generate a meaningful error message.
     */

    while (TclIsSpaceProcM(*p)) {
	p++;
    }
    if (*p == '+' || *p == '-') {
	p++;
    }
    if (*p == '0') {
	if ((p[1] == 'o') || p[1] == 'O') {
	    p+=2;
	}
	while (isdigit(UCHAR(*p))) {	/* INTL: digit. */
	    p++;
	}
	while (TclIsSpaceProcM(*p)) {
	    p++;
	}
	if (*p == '\0') {
	    /*
	     * Reached end of string.
	     */








|












|







3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
    register CONST char *p = value;

    /*
     * A frequent mistake is invalid octal values due to an unwanted leading
     * zero. Try to generate a meaningful error message.
     */

    while (TclIsSpaceProc(*p)) {
	p++;
    }
    if (*p == '+' || *p == '-') {
	p++;
    }
    if (*p == '0') {
	if ((p[1] == 'o') || p[1] == 'O') {
	    p+=2;
	}
	while (isdigit(UCHAR(*p))) {	/* INTL: digit. */
	    p++;
	}
	while (TclIsSpaceProc(*p)) {
	    p++;
	}
	if (*p == '\0') {
	    /*
	     * Reached end of string.
	     */

Changes to generic/tclVar.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static Tcl_HashEntry *	AllocVarEntry(Tcl_HashTable *tablePtr, void *keyPtr);
static void		FreeVarEntry(Tcl_HashEntry *hPtr);
static int		CompareVarKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static unsigned int	HashVarKey(Tcl_HashTable *tablePtr, void *keyPtr);

static Tcl_HashKeyType tclVarHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    TCL_HASH_KEY_DIRECT_COMPARE,/* allows compare keys by pointers */
    HashVarKey,			/* hashKeyProc */
    CompareVarKeys,		/* compareKeysProc */
    AllocVarEntry,		/* allocEntryProc */
    FreeVarEntry		/* freeEntryProc */
};

static inline Var *	VarHashCreateVar(TclVarHashTable *tablePtr,







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static Tcl_HashEntry *	AllocVarEntry(Tcl_HashTable *tablePtr, void *keyPtr);
static void		FreeVarEntry(Tcl_HashEntry *hPtr);
static int		CompareVarKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static unsigned int	HashVarKey(Tcl_HashTable *tablePtr, void *keyPtr);

static Tcl_HashKeyType tclVarHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    0,				/* flags */
    HashVarKey,			/* hashKeyProc */
    CompareVarKeys,		/* compareKeysProc */
    AllocVarEntry,		/* allocEntryProc */
    FreeVarEntry		/* freeEntryProc */
};

static inline Var *	VarHashCreateVar(TclVarHashTable *tablePtr,

Changes to library/auto.tcl.

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
# auto.tcl --
#
# utility procs formerly in init.tcl dealing with auto execution of commands
# and can be auto loaded themselves.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# auto_reset --
#
# Destroy all cached information for auto-loading and auto-execution, so that
# the information gets recomputed the next time it's needed.  Also delete any
# commands that are listed in the auto-load index.
#
# Arguments:
# None.

proc auto_reset {} {
    global auto_execs auto_index auto_path
    if {[array exists auto_index]} {
	foreach cmdName [array names auto_index] {
	    set fqcn [namespace which $cmdName]
	    if {$fqcn eq ""} {
		continue
	    }
	    rename $fqcn {}
	}
    }
    unset -nocomplain auto_execs auto_index ::tcl::auto_oldpath
    if {[catch {llength $auto_path}]} {
	set auto_path [list [info library]]

    } elseif {[info library] ni $auto_path} {
	lappend auto_path [info library]

    }
}

# tcl_findLibrary --
#
#	This is a utility for extensions that searches for a library directory
#	using a canonical searching algorithm. A side effect is to source the
#	initialization script and set a global library variable.
#
# Arguments:
# 	basename	Prefix of the directory name, (e.g., "tk")
#	version		Version number of the package, (e.g., "8.0")
#	patch		Patchlevel of the package, (e.g., "8.0.3")
#	initScript	Initialization script to source (e.g., tk.tcl)
#	enVarName	environment variable to honor (e.g., TK_LIBRARY)


|
|




|
|




|
|
|









|
<
<






>
|
|
>






|
|







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
# auto.tcl --
#
# utility procs formerly in init.tcl dealing with auto execution
# of commands and can be auto loaded themselves.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# auto_reset --
#
# Destroy all cached information for auto-loading and auto-execution,
# so that the information gets recomputed the next time it's needed.
# Also delete any commands that are listed in the auto-load index.
#
# Arguments:
# None.

proc auto_reset {} {
    global auto_execs auto_index auto_path
    if {[array exists auto_index]} {
	foreach cmdName [array names auto_index] {
	    set fqcn [namespace which $cmdName]
	    if {$fqcn eq ""} {continue}


	    rename $fqcn {}
	}
    }
    unset -nocomplain auto_execs auto_index ::tcl::auto_oldpath
    if {[catch {llength $auto_path}]} {
	set auto_path [list [info library]]
    } else {
	if {[info library] ni $auto_path} {
	    lappend auto_path [info library]
	}
    }
}

# tcl_findLibrary --
#
#	This is a utility for extensions that searches for a library directory
#	using a canonical searching algorithm. A side effect is to source
#	the initialization script and set a global library variable.
#
# Arguments:
# 	basename	Prefix of the directory name, (e.g., "tk")
#	version		Version number of the package, (e.g., "8.0")
#	patch		Patchlevel of the package, (e.g., "8.0.3")
#	initScript	Initialization script to source (e.g., tk.tcl)
#	enVarName	environment variable to honor (e.g., TK_LIBRARY)
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
    set errors {}

    # The C application may have hardwired a path, which we honor

    if {[info exists the_library] && $the_library ne ""} {
	lappend dirs $the_library
    } else {

	# Do the canonical search

	# 1. From an environment variable, if it exists.  Placing this first
	#    gives the end-user ultimate control to work-around any bugs, or
	#    to customize.

	if {[info exists env($enVarName)]} {
	    lappend dirs $env($enVarName)
	}

	# 2. In the package script directory registered within the
	#    configuration of the package itself.

	if {[catch {
	    ::${basename}::pkgconfig get scriptdir,runtime
	} value] == 0} {
	    lappend dirs $value
	}








>


|
|
|

|
|
|

|
|







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
    set errors {}

    # The C application may have hardwired a path, which we honor

    if {[info exists the_library] && $the_library ne ""} {
	lappend dirs $the_library
    } else {

	# Do the canonical search

	# 1. From an environment variable, if it exists.
	#    Placing this first gives the end-user ultimate control
	#    to work-around any bugs, or to customize.

        if {[info exists env($enVarName)]} {
            lappend dirs $env($enVarName)
        }

	# 2. In the package script directory registered within
	#    the configuration of the package itself.

	if {[catch {
	    ::${basename}::pkgconfig get scriptdir,runtime
	} value] == 0} {
	    lappend dirs $value
	}

96
97
98
99
100
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
	}

	# 3. Various locations relative to the executable
	# ../lib/foo1.0		(From bin directory in install hierarchy)
	# ../../lib/foo1.0	(From bin/arch directory in install hierarchy)
	# ../library		(From unix directory in build hierarchy)
	#
	# Remaining locations are out of date (when relevant, they ought to be
	# covered by the $::auto_path seach above) and disabled.
	#
	# ../../library		(From unix/arch directory in build hierarchy)
	# ../../foo1.0.1/library
	#		(From unix directory in parallel build hierarchy)
	# ../../../foo1.0.1/library
	#		(From unix/arch directory in parallel build hierarchy)

	set parentDir [file dirname [file dirname [info nameofexecutable]]]
	set grandParentDir [file dirname $parentDir]
	lappend dirs [file join $parentDir lib $basename$version]
	lappend dirs [file join $grandParentDir lib $basename$version]
	lappend dirs [file join $parentDir library]
	if {0} {
	    lappend dirs [file join $grandParentDir library]
	    lappend dirs [file join $grandParentDir $basename$patch library]
	    lappend dirs [file join [file dirname $grandParentDir] \
			      $basename$patch library]
	}
    }
    # uniquify $dirs in order
    array set seen {}
    foreach i $dirs {
	# Take note that the [file normalize] below has been noted to
	# cause difficulties for the freewrap utility.  See Bug 1072136.
	# Until freewrap resolves the matter, one might work around the
	# problem by disabling that branch.
	if {[interp issafe]} {
	    set norm $i
	} else {
	    set norm [file normalize $i]
	}
	if {[info exists seen($norm)]} {
	    continue
	}
	set seen($norm) {}

	lappend uniqdirs $i
    }
    set dirs $uniqdirs
    foreach i $dirs {
	set the_library $i
	set file [file join $i $initScript]

	# source everything when in a safe interpreter because
	# we have a source command, but no file exists command

	if {[interp issafe] || [file exists $file]} {
	    if {![catch {uplevel #0 [list source $file]} msg opts]} {
		return
	    } else {
		append errors "$file: $msg\n"
		append errors [dict get $opts -errorinfo]\n
	    }
	}
    }
    unset -nocomplain the_library
    set msg "Can't find a usable $initScript in the following directories: \n"
    append msg "    $dirs\n\n"
    append msg "$errors\n\n"
    append msg "This probably means that $basename wasn't installed properly.\n"
    error $msg
}


# ----------------------------------------------------------------------
# auto_mkindex
# ----------------------------------------------------------------------
# The following procedures are used to generate the tclIndex file from Tcl
# source files.  They use a special safe interpreter to parse Tcl source
# files, writing out index entries as "proc" commands are encountered.  This

# implementation won't work in a safe interpreter, since a safe interpreter
# can't create the special parser and mess with its commands.

if {[interp issafe]} {
    return	;# Stop sourcing the file here
}

# auto_mkindex --
# Regenerate a tclIndex file from Tcl source files.  Takes as argument the
# name of the directory in which the tclIndex file is to be placed, followed
# by any number of glob patterns to use in that directory to locate all of the
# relevant files.
#
# Arguments:
# dir -		Name of the directory in which to create an index.

# args -	Any number of additional arguments giving the names of files
#		within dir.  If no additional are given auto_mkindex will look
#		for *.tcl.

proc auto_mkindex {dir args} {
    if {[interp issafe]} {
	error "can't generate index within safe interpreter"
    }

    set oldDir [pwd]
    cd $dir
    set dir [pwd]

    append index "# Tcl autoload index file, version 2.0\n"
    append index "# This file is generated by the \"auto_mkindex\" command\n"
    append index "# and sourced to set up indexing information for one or\n"
    append index "# more commands.  Typically each line is a command that\n"
    append index "# sets an element in the auto_index array, where the\n"
    append index "# element name is the name of a command and the value is\n"
    append index "# a script that loads the command.\n\n"
    if {![llength $args]} {
	set args *.tcl
    }

    auto_mkindex_parser::init
    foreach file [lsort [glob -- {*}$args]] {
	if {[catch {auto_mkindex_parser::mkindex $file} msg opts] == 0} {
	    append index $msg
	} else {
	    cd $oldDir
	    return -options $opts $msg
	}
    }
    auto_mkindex_parser::cleanup

    set fid [open "tclIndex" w]
    puts -nonewline $fid $index
    close $fid
    cd $oldDir
}

# Original version of auto_mkindex that just searches the source code for
# "proc" at the beginning of the line.

proc auto_mkindex_old {dir args} {
    set oldDir [pwd]
    cd $dir
    set dir [pwd]
    append index "# Tcl autoload index file, version 2.0\n"
    append index "# This file is generated by the \"auto_mkindex\" command\n"
    append index "# and sourced to set up indexing information for one or\n"
    append index "# more commands.  Typically each line is a command that\n"
    append index "# sets an element in the auto_index array, where the\n"
    append index "# element name is the name of a command and the value is\n"
    append index "# a script that loads the command.\n\n"
    if {![llength $args]} {
	set args *.tcl
    }
    foreach file [lsort [glob -- {*}$args]] {
	set f ""
	set error [catch {
	    set f [open $file]
	    fconfigure $f -eofchar "\032 {}"
	    while {[gets $f line] >= 0} {
		if {[regexp {^proc[ 	]+([^ 	]*)} $line match procName]} {
		    set procName [lindex [auto_qualify $procName "::"] 0]
		    append index "set [list auto_index($procName)]"
		    append index " \[list source \[file join \$dir [list $file]\]\]\n"
		}
	    }







|
|







|
|
|
|
|



















|
<
<
|
<




|
|




|
|
|
|
|

|
|













|
|
|
>
|
|






|
|
|
|



<
|
|
|



|













|





|
|
|
|

|









|
|












|






<







97
98
99
100
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
136
137


138

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
	}

	# 3. Various locations relative to the executable
	# ../lib/foo1.0		(From bin directory in install hierarchy)
	# ../../lib/foo1.0	(From bin/arch directory in install hierarchy)
	# ../library		(From unix directory in build hierarchy)
	#
	# Remaining locations are out of date (when relevant, they ought
	# to be covered by the $::auto_path seach above) and disabled.
	#
	# ../../library		(From unix/arch directory in build hierarchy)
	# ../../foo1.0.1/library
	#		(From unix directory in parallel build hierarchy)
	# ../../../foo1.0.1/library
	#		(From unix/arch directory in parallel build hierarchy)

        set parentDir [file dirname [file dirname [info nameofexecutable]]]
        set grandParentDir [file dirname $parentDir]
        lappend dirs [file join $parentDir lib $basename$version]
        lappend dirs [file join $grandParentDir lib $basename$version]
        lappend dirs [file join $parentDir library]
	if {0} {
	    lappend dirs [file join $grandParentDir library]
	    lappend dirs [file join $grandParentDir $basename$patch library]
	    lappend dirs [file join [file dirname $grandParentDir] \
			      $basename$patch library]
	}
    }
    # uniquify $dirs in order
    array set seen {}
    foreach i $dirs {
	# Take note that the [file normalize] below has been noted to
	# cause difficulties for the freewrap utility.  See Bug 1072136.
	# Until freewrap resolves the matter, one might work around the
	# problem by disabling that branch.
	if {[interp issafe]} {
	    set norm $i
	} else {
	    set norm [file normalize $i]
	}
	if {[info exists seen($norm)]} { continue }


	set seen($norm) ""

	lappend uniqdirs $i
    }
    set dirs $uniqdirs
    foreach i $dirs {
        set the_library $i
        set file [file join $i $initScript]

	# source everything when in a safe interpreter because
	# we have a source command, but no file exists command

        if {[interp issafe] || [file exists $file]} {
            if {![catch {uplevel #0 [list source $file]} msg opts]} {
                return
            } else {
                append errors "$file: $msg\n"
		append errors [dict get $opts -errorinfo]\n
            }
        }
    }
    unset -nocomplain the_library
    set msg "Can't find a usable $initScript in the following directories: \n"
    append msg "    $dirs\n\n"
    append msg "$errors\n\n"
    append msg "This probably means that $basename wasn't installed properly.\n"
    error $msg
}


# ----------------------------------------------------------------------
# auto_mkindex
# ----------------------------------------------------------------------
# The following procedures are used to generate the tclIndex file
# from Tcl source files.  They use a special safe interpreter to
# parse Tcl source files, writing out index entries as "proc"
# commands are encountered.  This implementation won't work in a
# safe interpreter, since a safe interpreter can't create the
# special parser and mess with its commands.

if {[interp issafe]} {
    return	;# Stop sourcing the file here
}

# auto_mkindex --
# Regenerate a tclIndex file from Tcl source files.  Takes as argument
# the name of the directory in which the tclIndex file is to be placed,
# followed by any number of glob patterns to use in that directory to
# locate all of the relevant files.
#
# Arguments:
# dir -		Name of the directory in which to create an index.

# args -	Any number of additional arguments giving the
#		names of files within dir.  If no additional
#		are given auto_mkindex will look for *.tcl.

proc auto_mkindex {dir args} {
    if {[interp issafe]} {
        error "can't generate index within safe interpreter"
    }

    set oldDir [pwd]
    cd $dir
    set dir [pwd]

    append index "# Tcl autoload index file, version 2.0\n"
    append index "# This file is generated by the \"auto_mkindex\" command\n"
    append index "# and sourced to set up indexing information for one or\n"
    append index "# more commands.  Typically each line is a command that\n"
    append index "# sets an element in the auto_index array, where the\n"
    append index "# element name is the name of a command and the value is\n"
    append index "# a script that loads the command.\n\n"
    if {[llength $args] == 0} {
	set args *.tcl
    }

    auto_mkindex_parser::init
    foreach file [lsort [glob -- {*}$args]] {
        if {[catch {auto_mkindex_parser::mkindex $file} msg opts] == 0} {
            append index $msg
        } else {
            cd $oldDir
	    return -options $opts $msg
        }
    }
    auto_mkindex_parser::cleanup

    set fid [open "tclIndex" w]
    puts -nonewline $fid $index
    close $fid
    cd $oldDir
}

# Original version of auto_mkindex that just searches the source
# code for "proc" at the beginning of the line.

proc auto_mkindex_old {dir args} {
    set oldDir [pwd]
    cd $dir
    set dir [pwd]
    append index "# Tcl autoload index file, version 2.0\n"
    append index "# This file is generated by the \"auto_mkindex\" command\n"
    append index "# and sourced to set up indexing information for one or\n"
    append index "# more commands.  Typically each line is a command that\n"
    append index "# sets an element in the auto_index array, where the\n"
    append index "# element name is the name of a command and the value is\n"
    append index "# a script that loads the command.\n\n"
    if {[llength $args] == 0} {
	set args *.tcl
    }
    foreach file [lsort [glob -- {*}$args]] {
	set f ""
	set error [catch {
	    set f [open $file]

	    while {[gets $f line] >= 0} {
		if {[regexp {^proc[ 	]+([^ 	]*)} $line match procName]} {
		    set procName [lindex [auto_qualify $procName "::"] 0]
		    append index "set [list auto_index($procName)]"
		    append index " \[list source \[file join \$dir [list $file]\]\]\n"
		}
	    }
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
	cd $oldDir
	error $msg $info $code
	return -options $opts $msg
    }
}

# Create a safe interpreter that can be used to parse Tcl source files
# generate a tclIndex file for autoloading.  This interp contains commands for
# things that need index entries.  Each time a command is executed, it writes
# an entry out to the index file.

namespace eval auto_mkindex_parser {
    variable parser ""          ;# parser used to build index
    variable index ""           ;# maintains index as it is built
    variable scriptFile ""      ;# name of file being processed
    variable contextStack ""    ;# stack of namespace scopes
    variable imports ""         ;# keeps track of all imported cmds







|
|
|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
	cd $oldDir
	error $msg $info $code
	return -options $opts $msg
    }
}

# Create a safe interpreter that can be used to parse Tcl source files
# generate a tclIndex file for autoloading.  This interp contains
# commands for things that need index entries.  Each time a command
# is executed, it writes an entry out to the index file.

namespace eval auto_mkindex_parser {
    variable parser ""          ;# parser used to build index
    variable index ""           ;# maintains index as it is built
    variable scriptFile ""      ;# name of file being processed
    variable contextStack ""    ;# stack of namespace scopes
    variable imports ""         ;# keeps track of all imported cmds
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
	interp delete $parser
	unset parser
    }
}

# auto_mkindex_parser::mkindex --
#
# Used by the "auto_mkindex" command to create a "tclIndex" file for the given
# Tcl source file.  Executes the commands in the file, and handles things like
# the "proc" command by adding an entry for the index file.  Returns a string
# that represents the index file.
#
# Arguments:
#	file	Name of Tcl source file to be indexed.

proc auto_mkindex_parser::mkindex {file} {
    variable parser
    variable index
    variable scriptFile
    variable contextStack
    variable imports

    set scriptFile $file

    set fid [open $file]
    fconfigure $fid -eofchar "\032 {}"
    set contents [read $fid]
    close $fid

    # There is one problem with sourcing files into the safe interpreter:
    # references like "$x" will fail since code is not really being executed

    # and variables do not really exist.  To avoid this, we replace all $ with
    # \0 (literally, the null char) later, when getting proc names we will
    # have to reverse this replacement, in case there were any $ in the proc
    # name.  This will cause a problem if somebody actually tries to have a \0
    # in their proc name.  Too bad for them.
    set contents [string map [list \$ \0] $contents]

    set index ""
    set contextStack ""
    set imports ""

    $parser eval $contents

    foreach name $imports {
	catch {$parser eval [list _%@namespace forget $name]}
    }
    return $index
}

# auto_mkindex_parser::hook command
#
# Registers a Tcl command to evaluate when initializing the slave interpreter

# used by the mkindex parser.  The command is evaluated in the master
# interpreter, and can use the variable auto_mkindex_parser::parser to get to
# the slave

proc auto_mkindex_parser::hook {cmd} {
    variable initCommands

    lappend initCommands $cmd
}

# auto_mkindex_parser::slavehook command
#
# Registers a Tcl command to evaluate when initializing the slave interpreter
# used by the mkindex parser.  The command is evaluated in the slave
# interpreter.

proc auto_mkindex_parser::slavehook {cmd} {
    variable initCommands

    # The $parser variable is defined to be the name of the slave interpreter
    # when this command is used later.

    lappend initCommands "\$parser eval [list $cmd]"
}

# auto_mkindex_parser::command --
#
# Registers a new command with the "auto_mkindex_parser" interpreter that
# parses Tcl files.  These commands are fake versions of things like the
# "proc" command.  When you execute them, they simply write out an entry to a
# "tclIndex" file for auto-loading.
#
# This procedure allows extensions to register their own commands with the
# auto_mkindex facility.  For example, a package like [incr Tcl] might
# register a "class" command so that class definitions could be added to a
# "tclIndex" file for auto-loading.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.

proc auto_mkindex_parser::command {name arglist body} {
    hook [list auto_mkindex_parser::commandInit $name $arglist $body]
}

# auto_mkindex_parser::commandInit --
#
# This does the actual work set up by auto_mkindex_parser::command. This is
# called when the interpreter used by the parser is created.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.

proc auto_mkindex_parser::commandInit {name arglist body} {
    variable parser

    set ns [namespace qualifiers $name]
    set tail [namespace tail $name]
    if {$ns eq ""} {
	set fakeName [namespace current]::_%@fake_$tail
    } else {
	set fakeName [namespace current]::[string map {:: _} _%@fake_$name]
    }
    proc $fakeName $arglist $body

    # YUK!  Tcl won't let us alias fully qualified command names, so we can't
    # handle names like "::itcl::class".  Instead, we have to build procs with

    # the fully qualified names, and have the procs point to the aliases.

    if {[string match *::* $name]} {
	set exportCmd [list _%@namespace export [namespace tail $name]]
	$parser eval [list _%@namespace eval $ns $exportCmd]

	# The following proc definition does not work if you want to tolerate
	# space or something else diabolical in the procedure name, (i.e.,

	# space in $alias). The following does not work:
	#   "_%@eval {$alias} \$args"
	# because $alias gets concat'ed to $args.  The following does not work
	# because $cmd is somehow undefined
	#   "set cmd {$alias} \; _%@eval {\$cmd} \$args"
	# A gold star to someone that can make test autoMkindex-3.3 work
	# properly

	set alias [namespace tail $fakeName]
	$parser invokehidden proc $name {args} "_%@eval {$alias} \$args"
	$parser alias $alias $fakeName
    } else {
	$parser alias $name $fakeName
    }
    return
}

# auto_mkindex_parser::fullname --
#
# Used by commands like "proc" within the auto_mkindex parser.  Returns the
# qualified namespace name for the "name" argument.  If the "name" does not
# start with "::", elements are added from the current namespace stack to

# produce a qualified name.  Then, the name is examined to see whether or not
# it should really be qualified.  If the name has more than the leading "::",
# it is returned as a fully qualified name.  Otherwise, it is returned as a
# simple name.  That way, the Tcl autoloader will recognize it properly.

#
# Arguments:
# name -		Name that is being added to index.

proc auto_mkindex_parser::fullname {name} {
    variable contextStack

    if {![string match ::* $name]} {
	foreach ns $contextStack {
	    set name "${ns}::$name"
	    if {[string match ::* $name]} {
		break
	    }
	}
    }

    if {[namespace qualifiers $name] eq ""} {
	set name [namespace tail $name]
    } elseif {![string match ::* $name]} {
	set name "::$name"
    }

    # Earlier, mkindex replaced all $'s with \0.  Now, we have to reverse that
    # replacement.
    return [string map [list \0 \$] $name]
}

if {[llength $::auto_mkindex_parser::initCommands]} {
    return
}








|
|
|
|














<



|
|
>
|
|
|
|
|









|






|
>
|
|
<









|
|
|




|
|






|
|
|
|

|
|
|
|












|
|












|

|



|
|
>
|


|
|

|
|
>
|

|
|

|
|

|
|
|

|





<
|
|
|
>
|
|
|
|
>








|
|
|
|
|
|



|

|


|
|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
	interp delete $parser
	unset parser
    }
}

# auto_mkindex_parser::mkindex --
#
# Used by the "auto_mkindex" command to create a "tclIndex" file for
# the given Tcl source file.  Executes the commands in the file, and
# handles things like the "proc" command by adding an entry for the
# index file.  Returns a string that represents the index file.
#
# Arguments:
#	file	Name of Tcl source file to be indexed.

proc auto_mkindex_parser::mkindex {file} {
    variable parser
    variable index
    variable scriptFile
    variable contextStack
    variable imports

    set scriptFile $file

    set fid [open $file]

    set contents [read $fid]
    close $fid

    # There is one problem with sourcing files into the safe
    # interpreter:  references like "$x" will fail since code is not
    # really being executed and variables do not really exist.
    # To avoid this, we replace all $ with \0 (literally, the null char)
    # later, when getting proc names we will have to reverse this replacement,
    # in case there were any $ in the proc name.  This will cause a problem
    # if somebody actually tries to have a \0 in their proc name.  Too bad
    # for them.
    set contents [string map [list \$ \0] $contents]

    set index ""
    set contextStack ""
    set imports ""

    $parser eval $contents

    foreach name $imports {
        catch {$parser eval [list _%@namespace forget $name]}
    }
    return $index
}

# auto_mkindex_parser::hook command
#
# Registers a Tcl command to evaluate when initializing the
# slave interpreter used by the mkindex parser.
# The command is evaluated in the master interpreter, and can
# use the variable auto_mkindex_parser::parser to get to the slave


proc auto_mkindex_parser::hook {cmd} {
    variable initCommands

    lappend initCommands $cmd
}

# auto_mkindex_parser::slavehook command
#
# Registers a Tcl command to evaluate when initializing the
# slave interpreter used by the mkindex parser.
# The command is evaluated in the slave interpreter.

proc auto_mkindex_parser::slavehook {cmd} {
    variable initCommands

    # The $parser variable is defined to be the name of the
    # slave interpreter when this command is used later.

    lappend initCommands "\$parser eval [list $cmd]"
}

# auto_mkindex_parser::command --
#
# Registers a new command with the "auto_mkindex_parser" interpreter
# that parses Tcl files.  These commands are fake versions of things
# like the "proc" command.  When you execute them, they simply write
# out an entry to a "tclIndex" file for auto-loading.
#
# This procedure allows extensions to register their own commands
# with the auto_mkindex facility.  For example, a package like
# [incr Tcl] might register a "class" command so that class definitions
# could be added to a "tclIndex" file for auto-loading.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.

proc auto_mkindex_parser::command {name arglist body} {
    hook [list auto_mkindex_parser::commandInit $name $arglist $body]
}

# auto_mkindex_parser::commandInit --
#
# This does the actual work set up by auto_mkindex_parser::command
# This is called when the interpreter used by the parser is created.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.

proc auto_mkindex_parser::commandInit {name arglist body} {
    variable parser

    set ns [namespace qualifiers $name]
    set tail [namespace tail $name]
    if {$ns eq ""} {
        set fakeName [namespace current]::_%@fake_$tail
    } else {
        set fakeName [namespace current]::[string map {:: _} _%@fake_$name]
    }
    proc $fakeName $arglist $body

    # YUK!  Tcl won't let us alias fully qualified command names,
    # so we can't handle names like "::itcl::class".  Instead,
    # we have to build procs with the fully qualified names, and
    # have the procs point to the aliases.

    if {[string match *::* $name]} {
        set exportCmd [list _%@namespace export [namespace tail $name]]
        $parser eval [list _%@namespace eval $ns $exportCmd]

	# The following proc definition does not work if you
	# want to tolerate space or something else diabolical
	# in the procedure name, (i.e., space in $alias)
	# The following does not work:
	#   "_%@eval {$alias} \$args"
	# because $alias gets concat'ed to $args.
	# The following does not work because $cmd is somehow undefined
	#   "set cmd {$alias} \; _%@eval {\$cmd} \$args"
	# A gold star to someone that can make test
	# autoMkindex-3.3 work properly

        set alias [namespace tail $fakeName]
        $parser invokehidden proc $name {args} "_%@eval {$alias} \$args"
        $parser alias $alias $fakeName
    } else {
        $parser alias $name $fakeName
    }
    return
}

# auto_mkindex_parser::fullname --

# Used by commands like "proc" within the auto_mkindex parser.
# Returns the qualified namespace name for the "name" argument.
# If the "name" does not start with "::", elements are added from
# the current namespace stack to produce a qualified name.  Then,
# the name is examined to see whether or not it should really be
# qualified.  If the name has more than the leading "::", it is
# returned as a fully qualified name.  Otherwise, it is returned
# as a simple name.  That way, the Tcl autoloader will recognize
# it properly.
#
# Arguments:
# name -		Name that is being added to index.

proc auto_mkindex_parser::fullname {name} {
    variable contextStack

    if {![string match ::* $name]} {
        foreach ns $contextStack {
            set name "${ns}::$name"
            if {[string match ::* $name]} {
                break
            }
        }
    }

    if {[namespace qualifiers $name] eq ""} {
        set name [namespace tail $name]
    } elseif {![string match ::* $name]} {
        set name "::$name"
    }

    # Earlier, mkindex replaced all $'s with \0.  Now, we have to reverse
    # that replacement.
    return [string map [list \0 \$] $name]
}

if {[llength $::auto_mkindex_parser::initCommands]} {
    return
}

531
532
533
534
535
536
537
538
539
540
541
542
543
544

545
546
547
548
549
550
551
    # command is a little easier to read (otherwise it'd be full of
    # backslashed dollar signs, etc.
    append index [list set auto_index([fullname $name])] \
	    [format { [list source [file join $dir %s]]} \
	    [file split $scriptFile]] "\n"
}

# Conditionally add support for Tcl byte code files.  There are some tricky
# details here.  First, we need to get the tbcload library initialized in the
# current interpreter.  We cannot load tbcload into the slave until we have
# done so because it needs access to the tcl_patchLevel variable.  Second,
# because the package index file may defer loading the library until we invoke
# a command, we need to explicitly invoke auto_load to force it to be loaded.
# This should be a noop if the package has already been loaded


auto_mkindex_parser::hook {
    if {![catch {package require tbcload}]} {
	if {[namespace which -command tbcload::bcproc] eq ""} {
	    auto_load tbcload::bcproc
	}
	load {} tbcload $auto_mkindex_parser::parser







|
|
|
|
|
|
|
>







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
    # command is a little easier to read (otherwise it'd be full of
    # backslashed dollar signs, etc.
    append index [list set auto_index([fullname $name])] \
	    [format { [list source [file join $dir %s]]} \
	    [file split $scriptFile]] "\n"
}

# Conditionally add support for Tcl byte code files.  There are some
# tricky details here.  First, we need to get the tbcload library
# initialized in the current interpreter.  We cannot load tbcload into the
# slave until we have done so because it needs access to the tcl_patchLevel
# variable.  Second, because the package index file may defer loading the
# library until we invoke a command, we need to explicitly invoke auto_load
# to force it to be loaded.  This should be a noop if the package has
# already been loaded

auto_mkindex_parser::hook {
    if {![catch {package require tbcload}]} {
	if {[namespace which -command tbcload::bcproc] eq ""} {
	    auto_load tbcload::bcproc
	}
	load {} tbcload $auto_mkindex_parser::parser
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
		    [format { [list source [file join $dir %s]]} \
		    [file split $scriptFile]] "\n"
	}
    }
}

# AUTO MKINDEX:  namespace eval name command ?arg arg...?
# Adds the namespace name onto the context stack and evaluates the associated
# body of commands.
#
# AUTO MKINDEX:  namespace import ?-force? pattern ?pattern...?
# Performs the "import" action in the parser interpreter.  This is important
# for any commands contained in a namespace that affect the index.  For
# example, a script may say "itcl::class ...", or it may import "itcl::*" and

# then say "class ...".  This procedure does the import operation, but keeps
# track of imported patterns so we can remove the imports later.

auto_mkindex_parser::command namespace {op args} {
    switch -- $op {
	eval {
	    variable parser
	    variable contextStack

	    set name [lindex $args 0]
	    set args [lrange $args 1 end]

	    set contextStack [linsert $contextStack 0 $name]
	    $parser eval [list _%@namespace eval $name] $args
	    set contextStack [lrange $contextStack 1 end]
	}
	import {
	    variable parser
	    variable imports
	    foreach pattern $args {
		if {$pattern ne "-force"} {
		    lappend imports $pattern
		}
	    }
	    catch {$parser eval "_%@namespace import $args"}
	}
	ensemble {
	    variable parser
	    variable contextStack
	    if {[lindex $args 0] eq "create"} {
		set name ::[join [lreverse $contextStack] ::]
		# create artifical proc to force an entry in the tclIndex
		$parser eval [list ::proc $name {} {}]
	    }
	}
    }
}

return







|
|


|
|
|
>
|
|



|
|
|

|
|

|

|
|
|
|
|
|
|
|
|
|
|
|













565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
		    [format { [list source [file join $dir %s]]} \
		    [file split $scriptFile]] "\n"
	}
    }
}

# AUTO MKINDEX:  namespace eval name command ?arg arg...?
# Adds the namespace name onto the context stack and evaluates the
# associated body of commands.
#
# AUTO MKINDEX:  namespace import ?-force? pattern ?pattern...?
# Performs the "import" action in the parser interpreter.  This is
# important for any commands contained in a namespace that affect
# the index.  For example, a script may say "itcl::class ...",
# or it may import "itcl::*" and then say "class ...".  This
# procedure does the import operation, but keeps track of imported
# patterns so we can remove the imports later.

auto_mkindex_parser::command namespace {op args} {
    switch -- $op {
        eval {
            variable parser
            variable contextStack

            set name [lindex $args 0]
            set args [lrange $args 1 end]

            set contextStack [linsert $contextStack 0 $name]
	    $parser eval [list _%@namespace eval $name] $args
            set contextStack [lrange $contextStack 1 end]
        }
        import {
            variable parser
            variable imports
            foreach pattern $args {
                if {$pattern ne "-force"} {
                    lappend imports $pattern
                }
            }
            catch {$parser eval "_%@namespace import $args"}
        }
	ensemble {
	    variable parser
	    variable contextStack
	    if {[lindex $args 0] eq "create"} {
		set name ::[join [lreverse $contextStack] ::]
		# create artifical proc to force an entry in the tclIndex
		$parser eval [list ::proc $name {} {}]
	    }
	}
    }
}

return

Changes to library/clock.tcl.

3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
    # arbitrary start time in front of the transitions.

    binary scan $d @${seek}${iformat}${nTime}c${nTime} times tempCodes
    incr seek [expr { ($ilen + 1) * $nTime }]
    set times [linsert $times 0 $MINWIDE]
    set codes {}
    foreach c $tempCodes {
	lappend codes [expr { $c & 0xFF }]
    }
    set codes [linsert $codes 0 0]

    # Next come ${nType} time type descriptions, each of which has an
    # offset (seconds east of GMT), a DST indicator, and an index into
    # the abbreviation text.








|







3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
    # arbitrary start time in front of the transitions.

    binary scan $d @${seek}${iformat}${nTime}c${nTime} times tempCodes
    incr seek [expr { ($ilen + 1) * $nTime }]
    set times [linsert $times 0 $MINWIDE]
    set codes {}
    foreach c $tempCodes {
	lappend codes [expr { $c & 0xff }]
    }
    set codes [linsert $codes 0 0]

    # Next come ${nType} time type descriptions, each of which has an
    # offset (seconds east of GMT), a DST indicator, and an index into
    # the abbreviation text.

Changes to library/dde/pkgIndex.tcl.

1
2
3
4
5
6
7
if {![package vsatisfies [package provide Tcl] 8.5]} return
if {[info sharedlibextension] != ".dll"} return
if {[::tcl::pkgconfig get debug]} {
    package ifneeded dde 1.4.3 [list load [file join $dir tcldde14g.dll] Dde]
} else {
    package ifneeded dde 1.4.3 [list load [file join $dir tcldde14.dll] Dde]
}
|

|
|

|

1
2
3
4
5
6
7
if {![package vsatisfies [package provide Tcl] 8]} return
if {[info sharedlibextension] != ".dll"} return
if {[info exists ::tcl_platform(debug)]} {
    package ifneeded dde 1.3.3 [list load [file join $dir tcldde13g.dll] dde]
} else {
    package ifneeded dde 1.3.3 [list load [file join $dir tcldde13.dll] dde]
}

Deleted library/encoding/cns11643.enc.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
# Encoding file: cns11643, double-byte
D
2134 0 93
21
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00004E284E364E3F4E854E054E04518251965338536953B64E2A4E874E4951E2
4E464E8F4EBC4EBE516651E35204529C53B95902590A5B805DDB5E7A5E7F5EF4
5F505F515F61961D4E3C4E634E624EA351854EC54ECF4ECE4ECC518451865722
572351E45205529E529D52FD5300533A5C735346535D538653B7620953CC6C15
53CE57216C3F5E005F0C623762386534653565E04F0E738D4E974EE04F144EF1
4EE74EF74EE64F1D4F024F054F2256D8518B518C519951E55213520B52A60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
22
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000053225304530353075407531E535F536D538953BA53D0598053F653F753F9
597E53F4597F5B565724590459185932593059345DDF59755E845B825BF95C14
5FD55FD45FCF625C625E626462615E815E835F0D5F52625A5FCA5FC7623965EE
624F65E7672F6B7A6C39673F673C6C376C446C45738C75927676909390926C4B
6C4C4E214E204E224E684E894E984EF94EEF7F5182784EF84F064F034EFC4EEE
4F1690994F284F1C4F074F1A4EFA4F17514A962351724F3B51B451B351B20000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
23
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00004F6451E84F675214520F5215521852A84F33534B534F518F5350521C538B
522153BE52AE53D2541653FF538E540054305405541354155445541956E35735
57365731573258EE59054E545447593656E756E55741597A574C5986574B5752
5B865F535C1859985C3D5C78598E59A25990598F5C8059A15E085B925C285C2A
5C8D5EF55F0E5C8B5C895C925FD35FDA5C935FDB5DE0620F625D625F62676257
9F505E8D65EB65EA5F7867375FD2673267366B226BCE5FEE6C586C516C770000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
24
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006C3C5FFA6C5A5FF76C53706F7072706E6283628C707372B172B26287738F
627B627A6270793C6288808D808E6272827B65F08D718FB99096909A67454E24
4E7167554E9C4F454F4A4F394F37674B4F324F426C1A4F444F4B6C6B4F404F35
4F3151516C6F5150514E6C6D6C87519D6C9C51B551B851EC522352275226521F
522B522052B452B372C65325533B537473957397739373947392544D75397594
543A7681793D5444544C5423541A5432544B5421828F54345449545054220000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
25
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000543F5451545A542F8FC956E956F256F356EF56ED56EC56E6574896285744
573F573C575357564F85575F5743575857574F744F894F8457464F4C573D4F6A
57425754575558F158F258F0590B9EA656F1593D4F955994598C519E599C51BE
5235599F5233599B52315989599A530B658853925B8D54875BFE5BFF5BFD5C2B
54885C845C8E5C9C5465546C5C855DF55E09546F54615E0B54985E925E905F03
56F75F1E5F6357725FE75FFE5FE65FDC5FCE57805FFC5FDF5FEC5FF657620000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
26
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005FF25FF05FF95945621359BA59CF623B623C628259C159B659BC6278628B
59B1629E62A5629B629C6299628D6285629D62755C445C475CAE65F65CA05CB5
5CAF66F5675B5C9F675467525CA267586744674A67615CB66C7F6C916C9E5E14
6C6E6C7C6C9F6C755F246C566CA26C795F7D6CA15FE56CAA6CA0601970797077
707E600A7075707B7264601E72BB72BC72C772B972BE72B66011600C7398601C
6214623D62AD7593768062BE768376C076C162AE62B377F477F562A97ACC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
27
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007ACD7CFA809F80918097809466048286828C65FB8295660B866C66058FB5
8FBE8FC766F68FC190A990A4678E6792677690A896279626962B963396349629
4E3D679F4E9D4F934F8A677D67814F6D4F8E4FA04FA24FA14F9F4FA36C1D4F72
6CEC4F8C51566CD96CB651906CAD6CE76CB751ED51FE522F6CC3523C52345239
52B952B552BF53556C9D5376537A53936D3053C153C253D554856CCF545F5493
548954799EFE548F5469546D70915494546A548A708356FD56FB56F872D80000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
28
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000056FC56F6576557815763576772D1576E5778577F73A673A258F3594B594C
74DD74E8753F59AD753E59C4759859C259B076F176F076F577F859BF77F959C9
59B859AC7942793F79C559B759D77AFB5B607CFD5B965B9E5B945B9F5B9D80B5
5C005C1982A082C05C495C4A82985CBB5CC182A782AE82BC5CB95C9E5CB45CBA
5DF65E135E125E7782C35E9882A25E995E9D5EF8866E5EF98FD25F065F218FCD
5F255F558FD790B290B45F845F8360306007963D6036963A96434FCD5FE90000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
29
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000603D60084FC94FCB62BA62B24FDC62B762E462A74FDB4FC74FD662D562E1
62DD62A662C162C562C062DF62E062DE53976589539965A665BA54A165FF54A5
66176618660165FE54AE670C54B6676B67966782678A54BC67A354BE67A2678F
54B067F967806B266B276B686B69579D6B816BB46BD1578F57996C1C579A5795
58F4590D59536C976C6C6CDF5A006CEA59DD6CE46CD86CB26CCE6CC859F2708B
70887090708F59F570877089708D70815BA8708C5CD05CD872405CD75CCB0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007265726672685CC95CC772CD72D372DB5CD472CF73A773A3739E5CDF73AF
5DF95E2173AA739C5E2075427544753B75415E9B759B759E5F0779C479C379C6
6037603979C7607279CA604560537ACF7C767C747CFF7CFC6042605F7F5980A8
6058606680B0624280B362CF80A480B680A780AC630380A65367820E82C4833E
829C63006313631462FA631582AA62F082C9654365AA82A682B2662166326635
8FCC8FD98FCA8FD88FCF90B7661D90AD90B99637670F9641963E96B697510000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000097634E574E794EB24EB04EAF4EB14FD24FD567E44FBE4FB84FB04FB14FC8
67F667EE4FC64FCC4FE54FE34FB4516A67B2519F67C651C167CC51C251C35245
524867C967CA524F67EA67CB52C552CA52C453275358537D6BE053DD53DC53DA
53D954B96D1F54D054B454CA6D0A54A354DA54A46D1954B2549E549F54B56D1D
6D4254CD6D1854CC6D03570057AC5791578E578D579257A1579057A657A8709F
579C579657A770A170B470B570A958F572495909590872705952726E72CA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000059DF72E859EB59EF59F059D55A0D5A0459F95A0259F859E259D959E75B6A
73B473EB5BAB73C75C1B5C2F73C6663C73CB74EC74EE5CD15CDC5CE65CE15CCD
76795CE25CDD5CE55DFB5DFA5E1E76F75EA176FA77E75EFC5EFB5F2F78127805
5F66780F780E7809605C7813604E6051794B794560236031607C605279D66060
604A60617AD162187B017C7A7C787C797C7F7C807C81631F631762EA63216304
63057FBE6531654465408014654265BE80C76629661B80C86623662C661A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006630663B661E6637663880C9670E80D780E667E867D6822167C767BC6852
67BF67D567FE836367FB833A67B168016805680067D782F26B2A6B6B82FB82F6
82F082EA6BE182E082FA6D236CFF6D146D056D136D066D21884E6D156CAF6CF4
6D026D458A076D268FE36D448FEE6D2470A590BD70A390D570A270BB70A070AA
90C891D470A870B670B270A79653964A70B9722E5005723C5013726D5030501B
72E772ED503372EC72E572E24FF773C473BD73CF73C973C173D0503173CE0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000074ED74EB519374EF754975507546754A5261754D75A6525E525F525575A8
52CD530E76C776FF54E276FD77E6780A54F37804780B78075504781578085511
79D379D479D079D77A7C54F854E07A7D7A837A8257017AD47AD57AD37AD07AD2
7AFE7AFC7C777C7C7C7B57B657BF57C757D057B957C1590E594A7F8F80D35A2D
80CB80D25A0F810980E280DF80C65B6C822482F782D882DD5C565C5482F882FC
5CEE5CF182E95D0082EE5E2982D0830E82E2830B82FD517986765F6786780000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000605A60678675867D6088884288666081898C8A0560958A0660978C9F609C
8FF18FE78FE98FEF90C290BC632C90C690C06336634390CD90C9634B90C4633C
958163419CEC50324FF9501D4FFF50044FF05003635150024FFC4FF250245008
5036502E65C35010503850394FFD50564FFB51A351A651A1681A684951C751C9
5260526452595265526752575263682B5253682F52CF684452CE52D052D152CC
68266828682E550D54F46825551354EF54F554F9550255006B6D808255180000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
30
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000054F054F66BE86BE355196BE7570557C96D6357B757CD6D0D6D616D9257BE
57BB6D6D57DB57C857C457C557D157CA57C06D676D605A215A2A6D7C5A1D6D82
5A0B6D2F6D686D8B6D7E5A226D846D165A246D7B5A145A316D905A2F5A1A5A12
70DD70CB5A2670E270D75BBC5BBB5BB75C055C065C525C5370C770DA5CFA5CEB
72425CF35CF55CE95CEF72FA5E2A5E305E2E5E2C5E2F5EAF5EA973D95EFD5F32
5F8E5F935F8F604F609973D2607E73D46074604B6073607573E874DE60560000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
31
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000060A9608B60A6755B609360AE609E60A7624575C075BF632E75BA63526330
635B771B6319631B77126331635D6337633563537722635C633F654B78227835
658B7828659A66506646664E6640782A664B6648795B66606644664D79526837
682479EC79E0681B683679EA682C681968566847683E681E7A8B681568226827
685968586855683068236B2E6B2B6B306B6C7B096B8B7C846BE96BEA6BE56D6B
7C8D7C856D736D577D117D0E6D5D6D566D8F6D5B6D1C6D9A6D9B6D997F610000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
32
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006D816D717F5D7F5B6D726D5C6D9670C470DB70CC70D070E370DF80F270D6
70EE70D580FB81008201822F727A833372F573028319835173E273EC73D573F9
73DF73E683228342834E831B73E473E174F3834D831683248320755675557558
7557755E75C38353831E75B4834B75B18348865376CB76CC772A86967716770F
869E8687773F772B770E772486857721771877DD86A7869578247836869D7958
79598843796279DA79D9887679E179E579E879DB886F79E279F08874887C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
33
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008A128C477ADA7ADD8CA47ADB7ADC8D788DB57B0D7B0B7B147C8E7C868FF5
7C877C837C8B90048FFC8FF690D67D2490D990DA90E37D257F627F937F997F97
90DC90E47FC47FC6800A91D591E28040803C803B80F680FF80EE810481038107
506A506180F750605053822D505D82278229831F8357505B504A506250158321
505F506983188358506450465040506E50738684869F869B868986A68692868F
86A0884F8878887A886E887B88848873555055348A0D8A0B8A19553655350000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
34
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000553055525545550C8FF990099008553990DE9151553B554091DB91DF91DE
91D691E095859660965957F4965657ED57FD96BD57F8580B5042505958075044
50665052505450715050507B507C505857E758015079506C507851A851D151CF
5268527652D45A5553A053C45A385558554C55685A5F55495A6C5A53555D5529
5A43555455535A44555A5A48553A553F552B57EA5A4C57EF5A695A4757DD57FE
5A4257DE57E65B6E57E857FF580358F768A6591F5D1A595B595D595E5D0D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
35
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005D265A2B5D0F5A3B5D125D235A615A3A5A6E5A4B5A6B5EB45EB95A455A4E
5A685A3D5A715A3F5A6F5A7560905A735A2C5A595A545A4F5A6360CF60E45BC8
60DD5BC360B15C5B5C6160CA5D215D0A5D0960C05D2C5D08638A63825D2A5D15
639E5D105D1363975D2F5D18636F5DE35E395E355E3A5E32639C636D63AE637C
5EBB5EBA5F345F39638563816391638D6098655360D066656661665B60D760AA
666260A160A4688760EE689C60E7686E68AE60DE6956686F637E638B68A90000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
36
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000687563796386639368776373636A686B636C68AA637F687163B263BA6896
688B6366637468A4655A687B654E654D658D658E65AD6B3365C765CA6B9165C9
6B8D65E366576C2A66636667671A671967166DAC6DE9689E68B6689868736E00
689A688E68B768DB68A5686C68C168846DDB6DF46895687A68996DF068B868B9
68706DCF6B356DD06B906BBB6BED6DD76DCD6DE36DC16DC36DCE70F771176DAD
6E0470F06DB970F36DE770FC6E086E0671136E0A6DB070F66DF86E0C710E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
37
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006DB1727B6E026E076E096E016E176DFF6E12730A730871037107710170F5
70F1710870F2710F740170FE7407740073FA731A7310730E740273F374087564
73FB75CE75D275CF751B752375617568768F756775D37739772F769077317732
76D576D776D67730773B7726784877407849771E784A784C782678477850784B
7851784F78427846796B796E796C79F279F879F179F579F379F97A907B357B3B
7A9A7A937A917AE17B247B337B217B1C7B167B177B367B1F7B2F7C937C990000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
38
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007C9A7C9C7C947D497C967D347D377D3D7D2D7D367D4C7D457D2C7D487D41
7D477F3B7D3F7D4A7D3B7D288008801A7F9C801D7F9B8049804580447C9B7FD1
7FC7812A812E801F801E81318047811A8134811781258119811B831D83718384
8380837283A18127837983918211839F83AD823A8234832382748385839C83B7
8658865A8373865786B2838F86AE8395839983758845889C889488A3888F88A5
88A988A6888A88A0889089928991899483B08A268A328A2883AE83768A1C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
39
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000086568A2B8A2086C28A2986C586BA86B08A218C3A86B38C5B8C588C7C86BB
8CA68CAE8CAD8D6588528D7E88958D7C8D7F8D7A8DBD889188A18DC08DBB8EAD
8EAF8ED6889788A488AC888C88938ED9898289D69012900E90258A27901390EE
8C3990AB90F78C5D9159915491F291F091E591F68DC28DB995878DC1965A8EDE
8EDD966E8ED78EE08EE19679900B98E198E6900C9EC49ED24E8090F04E81508F
50975088508990EC90E950815160915A91535E4251D391F491F151D251D60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000527391F9527091EB91F791E853A853A653C5559755DE966D966B559655B4
96BF55859804559B55A0509B555950945586508B50A355AF557A508E509D5068
559E509255A9570F570E581A5312581F53A4583C5818583E582655AD583A5645
5822559358FB5963596455815AA85AA35A825A885AA15A855A9855955A99558E
5A895A815A965A80581E58275A91582857F5584858255ACF581B5833583F5836
582E58395A875AA0582C5A7959615A865AAB5AAA5AA45A8D5A7E5A785BD50000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005A7C5AA55AAC5C1E5C5F5C5E5D445D3E5A975D485D1C5AA95D5B5D4D5A8C
5A9C5D575A935D535D4F5BCD5D3B5D465BD15BCA5E465E475C305E485EC05EBD
5EBF5D4B5F115D355F3E5F3B5D555F3A5D3A5D525D3D5FA75D5960EA5D396107
6122610C5D325D3660B360D660D25E4160E360E560E95FAB60C9611160FD60E2
60CE611E61206121621E611663E263DE63E660F860FC60FE60C163F8611863FE
63C163BF63F763D1655F6560656163B063CE65D163E863EF667D666B667F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000063CA63E066736681666D6669646163DF671E68ED63DC63C463D863D36903
63C768FE68E5691E690263D763D9690968CA690065646901691868E268CF659D
692E68C568FF65D2691C68C3667B6B6F66716B6E666A6BBE67016BF46C2D6904
6DB66E756E1E68EA6E18690F6E4868F76E4F68E46E426E6A6E706DFE68E16907
6E6D69086E7B6E7E6E5968EF6E5769146E806E5068FD6E296E766E2A6E4C712A
68CE7135712C7137711D68F468D1713868D47134712B7133712771246B3B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000712D7232728372827287730673247338732A732C732B6DFC732F73287417
6E496E88741974386E45741F7414743C73F7741C74157418743974F975246E51
6E3B6E03756E756D7571758E6E6175E56E286E606E716E6B769476B36E3076D9
6E657748774977436E776E55774277DF6E66786378766E5A785F786679667971
712E713179767984797579FF7A0771287A0E7A09724B725A7288728972867285
7AE77AE27B55733073227B437B577B6C7B427B5373267B417335730C7CA70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007CA07CA67CA47D74741A7D59742D7D607D577D6C7D7E7D6474207D5A7D5D
752F756F756C7D767D4D7D7575E67FD37FD675E475D78060804E8145813B7747
814881428149814081148141774C81EF81F68203786483ED785C83DA841883D2
8408787084007868785E786284178346841483D38405841F8402841683CD83E6
7AE6865D86D586E17B447B487B4C7B4E86EE884788467CA27C9E88BB7CA188BF
88B47D6388B57D56899A8A437D4F7D6D8A5A7D6B7D527D548A358A388A420000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008A498A5D8A4B8A3D7F667FA27FA07FA18C608C5E8C7F8C7E8C8380D48CB1
8D878152814F8D888D83814D813A8D868D8B8D828DCA8DD28204823C8DD48DC9
8EB0833B83CF83F98EF28EE48EF38EEA83E78EFD83FC8F9D902B902A83C89028
9029902C840183DD903A90309037903B83CB910A83D683F583C991FE922083DE
920B84069218922283D5921B920883D1920E9213839A83C3959583EE83C483FB
968C967B967F968183FE968286E286E686D386E386DA96EE96ED86EB96EC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
40
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000975F976F86D7976D86D188488856885588BA88D798F088B888C088BE9AA9
88BC88B79AE04EB7890188C950CC50BC899750AA50B989DB50AB50C350CD517E
527E52798A588A4452E152E052E7538053AB53AA53A953E055EA8C8055D78CBE
8CB055C157158D84586C8D89585C58505861586A5869585658605866585F5923
596659688EEF8EF75ACE8EF95AC55AC38EE58EF55AD08EE88EF68EEB8EF18EEC
8EF45B745B765BDC5BD75BDA5BDB91045C205D6D5D6690F95D645D6E91000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
41
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005D605F425F5A5F6E9164915F6130613A612A614361196131921A613D920F
920C92006408643264389206643192276419921C6411921992176429641D957B
958D958C643C96876446644796899683643A640796C8656B96F16570656D9770
65E4669398A998EB9CE69EF9668F4E844EB6669250BF668E50AE694650CA50B4
50C850C250B050C150BA693150CB50C9693E50B8697C694352786973527C6955
55DB55CC6985694D69506947696769366964696155BF697D6B446B406B710000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
42
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B736B9C55C855F255CD6BC155C26BFA6C316C325864584F6EB86EA8586F
6E916EBB585D6E9A5865585B6EA9586358716EB56E6C6EE85ACB6EDD6EDA6EE6
6EAC5AB05ABF5AC86ED96EE36EE96EDB5ACA716F5AB65ACD71485A90714A716B
5BD9714F715771745D635D4A5D6571457151716D5D6872517250724E5E4F7341
5E4A732E73465EC574275EC674487453743D5FAF745D74566149741E74477443
74587449612E744C7445743E61297501751E91686223757A75EE760276970000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
43
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007698641064126409775D77647753775878827890788A6439787A787D6423
788B787864306428788D788878927881797E798364256427640B7980641B642E
64217A0F656F65927A1D66867AA17AA466907AE97AEA66997B627B6B67207B5E
695F7B79694E69627B6F7B686945696A7CAE6942695769597CB069487D906935
7D8A69337D8B7D997D9569787D877D787D977D897D986976695869417FA3694C
693B694B7FDD8057694F8163816A816C692F697B693C815D81756B43815F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
44
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B48817D816D6BFB6BFC8241844F84846E9B847F6EC88448842A847B8472
8464842E845C84536EC6844184C86EC184628480843E848384716EA6844A8455
84586EC36EDC6ED886FC86FD87156E8D871686FF6EBF6EB36ED0885888CF88E0
6EA371477154715289E78A6A8A80715D8A6F8A6571788A788A7D8A8871587143
8A648A7E715F8A678C638C88714D8CCD724F8CC9728C8DED7290728E733C7342
733B733A73408EB1734974448F048F9E8FA090439046904890459040904C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
45
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000074427446910C9113911574FF916B9167925D9255923569839259922F923C
928F925C926A9262925F926B926E923B92449241959A7699959976DD7755775F
968F77529696775A7769776796F496FC776D9755788797797894788F788497EE
97F57886980B788398F37899788098F798FF98F5798298EC98F17A117A18999A
7A129AE29B3D9B5D9CE87A1B9CEB9CEF9CEE9E819F1450D050D950DC50D87B69
50E150EB7B737B7150F450E250DE7B767B637CB251F47CAF7D887D8652ED0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
46
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000052EA7D7F53327D7A53AE53B07D8355FB5603560B7D8456077D9255F87F6B
5628561E7F6C5618561156515605571758928164588C817758785884587358AD
58975895587758725896588D59108161596C82495AE782405AE4824584F15AEF
5626847684795AF05D7B84655D83844084865D8B5D8C844D5D785E5284598474
5ED05ECF85075FB35FB4843A8434847A617B8478616F6181613C614261386133
844261606169617D6186622C62288452644C84C56457647C8447843664550000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
47
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000064626471646A6456643B6481846E644F647E646486F7870C86FA86D686F5
657186F8870E66A5669A669C870D66A688D666A4698F69C569C8699269B288CC
88D0898569E369C069D669D1699F69A269D289DC89E68A7669E169D5699D8A3F
8A7769988A846B746BA18A816EF06EF38C3C8C4B6F1B6F0C6F1D6F346F286F17
8C856F446F426F046F116EFA6F4A7191718E8D93718B718D717F718C717E717C
71838DEE71888DE98DE372948DE773557353734F7354746C7465746674610000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
48
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000746B746874768F0B7460903F74747506760E91107607910F911176B99114
76B776E2916E7774777777767775923A777877719265777A715B777B78A678AE
78B8926C924F926078B178AF923679897987923192547A2992507A2A924E7A2D
7A2C92567A32959F7AEC7AF07B817B9E7B8396917B9296CE7BA37B9F7B9396F5
7B867CB87CB79772980F980D980E98AC7DC87DB699AF7DD199B07DA87DAB9AAB
7DB37DCD9CED7DCF7DA49EFD50E67F417F6F7F7150F350DB50EA50DD50E40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
49
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000050D38023805B50EF8061805F818152805281818482135330824A824C5615
560C561284BD8495561C849284C35602849684A584B584B384A384E484D884D5
589884B784AD84DA84938736587A58875891873D872B87478739587B8745871D
58FE88FF88EA5AEE88F55AD5890088ED890388E95AF35AE289EA5ADB8A9B8A8E
8AA25AD98A9C8A948A908AA98AAC5C638A9F5D805D7D8A9D5D7A8C675D775D8A
8CD08CD68CD48D988D9A8D975D7F5E585E598E0B8E088E018EB48EB35EDC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008FA18FA25ED2905A5F449061905F5FB6612C9125917B9176917C61739289
92F692B192AD929292819284617A92AE9290929E616A6161615695A295A7622B
642B644D645B645D96A0969D969F96D0647D96D1646664A6975964829764645C
644B64539819645098149815981A646B645964656477990665A098F89901669F
99BE99BC99B799B699C069C999B869CE699669B099C469BC99BF69999ADA9AE4
9AE99AE89AEA9AE569BF9B2669BD69A49B4069B969CA699A69CF69B369930000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000069AA9EBD699E69D969976990510E69B550F769C650FC510D510151DA51D9
51DB5286528E52EE533353B16EF15647562D56546F37564B5652563156445656
5650562B6F18564D5637564F58A258B76F7358B26EEE58AA58B558B06F3C58B4
58A458A76F0E59265AFE6EFD5B046F395AFC6EFC5B065B0A5AFA5B0D5B005B0E
7187719071895D9171855D8F5D905D985DA45D9B5DA35D965DE45E5A72957293
5E5E734D5FB86157615C61A661956188747261A3618F75006164750361590000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006178761661856187619E7611760A6198619C7781777C622F6480649B648E
648D649464C678B264A8648378AD64B9648664B464AF649178A064AA64A164A7
66B666B3798B66BC66AC799466AD6A0E79886A1C6A1A7A2B7A4A6A0B7A2F69EF
6A0C69F06A227AAC69D87B886A1269FA7B916A2A7B966A107B8C7B9B6A2969F9
69EA6A2C6A247BA469E96B526B4F6B537CBA7DA76F106F656F757DAA7DC17DC0
7DC56FD07DCE6F5C6F3D6F717DCC6F916F0B6F796F816F8F7DA66F596F740000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007DA171AE7F7371A371AD7FE57FDE71AB71A671A2818952F2725772557299
734B747A8215849784A4748C748484BA84CE74827493747B84AB750984B484C1
84CD84AA849A84B1778A849D779084BB78C678D378C078D278C778C284AF799F
799D799E84B67A4184A07A387A3A7A4284DB84B07A3E7AB07BAE7BB38728876B
7BBF872E871E7BCD87197BB28743872C8741873E8746872087327CC47CCD7CC2
7CC67CC37CC97CC787427DF887277DED7DE2871A873087117DDC7E027E010000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000088F27DD688FE7DE47DFE88F67E007DFC7DFD88EB7DF57DFF899F7DEB7DE5
7F787FAE7FE78A998065806A80668068806B819481A18192819681938D968E09
85018DFF84F88DFD84F58E0385048E068E058DFE8E00851B85038533853484ED
9123911C853591228505911D911A91249121877D917A91729179877192A5885C
88E6890F891B92A089A989A589EE8AB1929A8ACC8ACE92978AB792A38AB58AE9
8AB492958AB38AC18AAF8ACA8AD09286928C92998C8E927E92878CE98CDB0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000928B8CEB8DA496A18DA28D9D977D977A977E97838E2A8E28977B97848EB8
8EB68EB98EB78F228F2B8F278F198FA499078FB3999C9071906A99BB99BA9188
918C92BF92B892BE92DC92E59B3F9B6092D492D69CF192DA92ED92F392DB5103
92B992E292EB95AF50F695B295B3510C50FD510A96A396A552F152EF56485642
970A563597879789978C97EF982A98225640981F563D9919563E99CA99DA563A
571A58AB99DE99C899E058A39AB69AB558A59AF458FF9B6B9B699B729B630000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
50
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005AF69D0D5AF89D019D0C5B019CF85B055B0F9CFE9D029E845D9F9EAB9EAA
511D51165DA0512B511E511B5290529453145E605E5C56675EDB567B5EE1565F
5661618B6183617961B161B061A2618958C358CA58BB58C058C459015B1F5B18
5B115B1561B35B125B1C64705B225B795DA664975DB35DAB5EEA648A5F5B64A3
649F61B761CE61B961BD61CF61C06199619765B361BB61D061C4623166B764D3
64C06A006A066A1769E564DC64D164C869E464D566C369EC69E266BF66C50000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
51
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000069FE66CD66C167066A1467246A636A426A5269E66A436A3369FC6A6C6A57
6A046A4C6A6E6A0F69F66A266A0769F46A376B516A716A4A6A366BA66A536C00
6A456A706F416F266A5C6B586B576F926F8D6F896F8C6F626F4F6FBB6F5A6F96
6FBE6F6C6F826F556FB56FD36F9F6F576FB76FF571B76F0071BB6F6B71D16F67
71BA6F5371B671CC6F7F6F9571D3749B6F6A6F7B749674A2749D750A750E719A
7581762C76377636763B71A476A171AA719C779871B37796729A735873520000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
52
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000078D678EB736078DC735B79A579A998347A537A4574897A4F74867ABD7ABB
7AF17488747C7BEC7BED7507757E7CD3761E7CE1761D7E197623761A76287E27
7E26769D769E806E81AF778F778981AD78CD81AA821878CC78D178CE78D4856F
854C78C48542799A855C8570855F79A2855A854B853F878A7AB4878B87A1878E
7BBE7BAC8799885E885F892489A78AEA8AFD8AF98AE38AE57DDB7DEA8AEC7DD7
7DE17E037DFA8CF27DF68CEF7DF08DA67DDF7F767FAC8E3B8E437FED8E320000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
53
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008F318F307FE68F2D8F3C8FA78FA5819F819E819591379195918E82169196
82539345930A824E825192FD9317931C930793319332932C9330930393058527
95C284FB95B884FA95C1850C84F4852A96AB96B784F784EB97159714851284EA
970C971784FE9793851D97D2850284FD983698319833983C982E983A84F0983D
84F998B5992299239920991C991D866299A0876399EF99E899EB877387588754
99E199E68761875A9AF89AF5876D876A9B839B949B84875D9B8B9B8F877A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
54
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009B8C875C9B89874F9B8E8775876287679D249D0F89059D139D0A890B8917
891889199D2A9D1A89119D279D169D2189A49E859EAC9EC69EC59ED79F538AB8
5128512751DF8AD5533553B38ABE568A567D56898AC358CD58D08AD95B2B5B33
5B295B355B315B375C365DBE8CDD5DB98DA05DBB8DA161E261DB61DD61DC61DA
8E2E61D98E1B8E1664DF8E198E2664E18E1464EE8E1865B566D466D58E1A66D0
66D166CE66D78F208F236A7D6A8A90736AA7906F6A996A826A88912B91290000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
55
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006A8691326A986A9D918591866A8F91816AAA91846B5D92D06C0A92C46FD7
6FD66FE592CF92F192DF6FD96FDA6FEA92DD6FF692EF92C271E392CA71E992CE
71EB71EF71F371EA92E092DE92E792D192D3737192E174AE92C674B3957C74AC
95AB95AE75837645764E764476A376A577A677A4978A77A977AF97D097CF981E
78F078F878F198287A49981B982798B27AC27AF27AF37BFA99167BF67BFC7C18
7C087C1299D399D47CDB7CDA99D699D899CB7E2C7E4D9AB39AEC7F467FF60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
56
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000802B807481B881C89B679B749B71859285939B75857F85AB85979B6C9CFC
85AC9CFD9CFF9CF787CE9D0087CD9CFB9D0887C187B187C79ED389409F10893F
893951178943511151DE533489AB56708B1F8B098B0C566656638C4056728C96
56778CF68CF758C88E468E4F58BF58BA58C28F3D8F4193669378935D93699374
937D936E93729373936293489353935F93685DB1937F936B5DB595C45DAE96AF
96AD96B25DAD5DAF971A971B5E685E665E6F5EE9979B979F5EE85EE55F4B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
57
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005FBC5FBB619D61A86196984061B4984761C198B761BA61BF61B8618C64D7
99A264D064CF9A0099F3648964C399F564F364D99ABD9B009B0265A29B349B49
9B9F66CA9BA39BCD9B999B9D66BA66CC9D396A349D446A496A679D356A686A3E
9EAF6A6D512F6A5B6A519F8E6A5A569F569B569E5696569456A06A4F5B3B6A6F
6A695B3A5DC15F4D5F5D61F36A4D6A4E6A466B5564F664E564EA64E765056BC8
64F96C046C036C066AAB6AED6AB26AB06AB56ABE6AC16AC86FC46AC06ABC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
58
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006AB16AC46ABF6FA56FAE700870036FFD7010700270136FA271FA720074B9
74BC6FB2765B7651764F76EB77B871D677B977C177C077BE790B71C77907790A
790871BC790D7906791579AF729E736973667AF5736C73657C2E736A7C1B749A
7C1A7C24749274957CE67CE37580762F7E5D7E4F7E667E5B7F477FB476327630
76BB7FFA802E779D77A181CE779B77A282197795779985CC85B278E985BB85C1
78DE78E378DB87E987EE87F087D6880E87DA8948894A894E894D89B189B00000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
59
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000089B37AB78B388B327BE78B2D7BD58B347BDA8B298C747BD47BEA8D037BDC
7BEB8DA98E587CD27CD48EBF8EC18F4A8FAC7E219089913D913C91A993A07E0E
93907E159393938B93AD93BB93B87E0D7E14939C95D895D77F7B7F7C7F7A975D
97A997DA8029806C81B181A6985481B99855984B81B0983F98B981B281B781A7
81F29938993699408556993B993999A4855385619A089A0C85469A1085419B07
85449BD285479BC29BBB9BCC9BCB854E856E9D4D9D639D4E85609D509D550000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000855D9D5E85659E909EB29EB186649ECA9F029F279F26879356AF58E058DC
87965B39877987875B7C5BF3879087915C6B5DC4650B6508650A8789891E65DC
8930892D66E166DF6ACE6AD46AE36AD76AE2892C891F89F18AE06AD86AD56AD2
8AF58ADD701E702C70256FF37204720872158AE874C474C974C774C876A977C6
77C57918791A79208CF37A667A647A6A8DA78E338E3E8E388E408E457C357C34
8E3D8E417E6C8E3F7E6E7E718F2E81D481D6821A82628265827685DB85D60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000908685E79133913585F4919387FD87D58807918F880F87F89308931F8987
930F89B589F5933C8B3F8B438B4C93018D0B8E6B8E688E708E758E7792FA8EC3
92F993E993EA93CB93C593C6932993ED93D3932A93E5930C930B93DB93EB93E0
93C1931695BC95DD95BE95B995BA95B695BF95B595BD96A996D497B297B497B1
97B597F2979497F097F89856982F98329924994499279A269A1F9A189A219A17
99E49B0999E399EA9BC59BDF9AB99BE39AB49BE99BEE9AFA9AF99D669D7A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009B809D6E9D919D839D769D7E9D6D9B939E959EE39B7A9B959F039F049D25
9F179D2051369D1453369D1D5B429D229D105B445B465B7E5DCA5DC85DCC5EF0
9ED5658566E566E79F3D512651256AF451246AE9512952F45693568C568D703D
56847036567E7216567F7212720F72177211720B5B2D5B2574CD74D074CC74CE
74D15B2F75895B7B7A6F7C4B7C445E6C5E6A5FBE61C361B57E7F8B7161E0802F
807A807B807C64EF64E964E385FC861086026581658085EE860366D2860D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000086138608860F881888126A9B6AA18967896589BB8B698B626A838B6E6AA4
8B616A7F8B648B4D8C516A8C6A928E838EC66C09941F6FA99404941794089405
6FED93F3941E9402941A941B9427941C71E196B571E871F2973371F097349731
97B897BA749797FC74AB749098C374AD994D74A59A2F7510751175129AC97584
9AC89AC49B2A9B389B5076E99C0A9BFB9C049BFC9BFE77B477B177A89C029BF6
9C1B9BF99C159C109BFF9C009C0C78F978FE9D959DA579A87A5C7A5B7A560000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009E989EC17A5A9F5A516456BB7C0558E65B495BF77BFF7BFB5DD07BF45FC2
7BF365117C096AFF6AFE6AFD7BFD6B017BF07BF1704B704D704774D376687667
7E33984877D179307932792E7E479F9D7AC97AC87E3B7C567C517E3A7F457F7F
7E857E897E8E7E84802C826A862B862F862881C586168615861D881A825A825C
858389BC8B758B7C85958D118D128F5C91BB85A493F4859E8577942D858985A1
96E497379736976797BE97BD97E29868986698C898CA98C798DC8585994F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000099A99A3C85909A3B9ACE87BE9B149B5387C59C2E87AC9C1F87B587BC87AE
87C99DB09DBD87CC87B79DAE9DC49E7B87B487B69E9E87B89F0587DE9F699FA1
56C7571D5B4A5DD389525F72620289AD62356527651E651F8B1E8B186B076B06
8B058B0B7054721C72207AF88B077C5D7C588B067E927F4E8B1A8C4F8C708827
8C718B818B838C948C448D6F8E4E8E4D8E539442944D9454944E8F409443907E
9138973C974097C09199919F91A1919D995A9A5193839ADD936493569C380000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
60
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000937C9C459C3A93769C359350935193609EF1938F9F93529A937993578641
5DD7934F65289377937B936170537059936772219359766F793779B57C627C5E
7CF596AE96B0863D9720882D89898B8D8B878B908D1A8E99979E979D97D5945F
97F1984194569461945B945A945C9465992B9741992A9933986E986C986D9931
99AA9A5C9A589ADE9A029C4F9C5199F79C5399F899F699FB9DFC9F3999FC513E
9ABE56D29AFD5B4F6B149B487A727A739B9E9B9B9BA68B919BA59BA491BF0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
61
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009BA2946C9BAF9D3396E697459D3697C897E4995D9D389B219D459B2C9B57
9D3E9D379C5D9C619C659E089E8A9E899E8D9EB09EC89F459EFB9EFF620566EF
6B1B6B1D722572247C6D512E8642864956978978898A8B9759708C9B8D1C5C6A
8EA25E6D5E6E61D861DF61ED61EE61F161EA9C6C61EB9C6F61E99E0E65049F08
9F1D9FA3650364FC5F606B1C66DA66DB66D87CF36AB98B9B8EA791C46ABA947A
6AB76AC79A619A639AD79C766C0B9FA5700C7067700172AB864A897D8B9D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
62
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008C538F65947B6FFC98CD98DD72019B309E16720371FD737674B874C096E7
9E189EA274B69F7C74C27E9E9484765C9E1C76597C7197CA7657765A76A69EA3
76EC9C7B9F97790C7913975079097910791257275C1379AC7A5F7C1C7C297C19
7C205FC87C2D7C1D7C267C287C2267657C307E5C52BD7E565B667E5865F96788
6CE66CCB7E574FBD5F8D7FB36018604880756B2970A681D07706825E85B485C6
5A105CFC5CFE85B385B585BD85C785C485BF70C985CE85C885C585B185B60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
63
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000085D28624957985B796BA866987E787E687E287DB87EB87EA7B29812887F3
8A2E87D487DC87D39AD987D8582B584587D963FA87F487E887DD6E86894B894F
894C89468950586789495BDD656E8B238B338B308C878B4750D250DF8B3E8B31
8B258B3769BA8B366B9D8B2480598B3D8B3A8C428C758C998C988C978CFE8D04
8D028D008E5C6F8A8E608E577BC37BC28E658E678E5B8E5A90F68E5D98238E54
8F468F478F488F4B71CD7499913B913E91A891A591A7984291AA93B5938C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
64
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000093927F84939B939D938993A7938E8D0E939E9861939593888B73939F9C27
938D945877D69B2D93A493A893B493A395D295D395D196B396D796DA5DC296DF
96D896DD97239722972597AC97AE97A84F664F684FE7503F97A550A6510F523E
53245365539B517F54CB55735571556B55F456225620569256BA569156B05759
578A580F581258135847589B5900594D5AD15AD35B675C575C775CD55D755D8E
5DA55DB65DBF5E655ECD5EED5F945F9A5FBA6125615062A36360636463B60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
65
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000640364B6651A7A255C2166E2670267A467AC68106806685E685A692C6929
6A2D6A776A7A6ACA6AE66AF56B0D6B0E6BDC6BDD6BF66C1E6C636DA56E0F6E8A
6E846E8B6E7C6F4C6F486F496F9D6F996FF8702E702D705C79CC70BF70EA70E5
71117112713F7139713B713D71777175717671717196719371B471DD71DE720E
591172187347734873EF7412743B74A4748D74B47673767776BC7819781B783D
78537854785878B778D878EE7922794D7986799979A379BC7AA77B377B590000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
66
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007BD07C2F7C327C427C4E7C687CA97CED7DD07E077DD37E647F40791E8041
806380BB6711672582488310836283128421841E84E284DE84E1857385D485F5
863786458672874A87A987A587F5883488508887895489848B038C528CD88D0C
8D188DB08EBC8ED58FAA909C85E8915C922B9221927392F492F5933F93429386
93BE93BC93BD93F193F293EF94229423942494679466959795CE95E7973B974D
98E499429B1D9B9889629D4964495E715E8561D3990E8002781E898889B70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
67
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005528557255BA55F055EE56B856B956C4805392B08B558B518B428B528B57
8C438C778C768C9A8D068D078D098DAC8DAA8DAD8DAB8E6D8E788E738E6A8E6F
8E7B8EC28F528F518F4F8F508F538FB49140913F91B091AD93DE93C793CF93C2
93DA93D093F993EC93CC93D993A993E693CA93D493EE93E393D593C493CE93C0
93D293A593E7957D95DA95DB96E19729972B972C9728972697B397B797B697DD
97DE97DF985C9859985D985798BF98BD98BB98BE99489947994399A699A70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
68
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009A1A9A159A259A1D9A249A1B9A229A209A279A239A1E9A1C9A149AC29B0B
9B0A9B0E9B0C9B379BEA9BEB9BE09BDE9BE49BE69BE29BF09BD49BD79BEC9BDC
9BD99BE59BD59BE19BDA9D779D819D8A9D849D889D719D809D789D869D8B9D8C
9D7D9D6B9D749D759D709D699D859D739D7B9D829D6F9D799D7F9D879D689E94
9E919EC09EFC9F2D9F409F419F4D9F569F579F58533756B256B556B358E35B45
5DC65DC75EEE5EEF5FC05FC161F9651765166515651365DF66E866E366E40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
69
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006AF36AF06AEA6AE86AF96AF16AEE6AEF703C7035702F7037703470317042
7038703F703A7039702A7040703B703370417213721472A8737D737C74BA76AB
76AA76BE76ED77CC77CE77CF77CD77F279257923792779287924792979B27A6E
7A6C7A6D7AF77C497C487C4A7C477C457CEE7E7B7E7E7E817E807FBA7FFF8079
81DB81D982688269862285FF860185FE861B860085F6860486098605860C85FD
8819881088118817881388168963896689B989F78B608B6A8B5D8B688B630000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008B658B678B6D8DAE8E868E888E848F598F568F578F558F588F5A908D9143
914191B791B591B291B3940B941393FB9420940F941493FE9415941094289419
940D93F5940093F79407940E9416941293FA940993F8943C940A93FF93FC940C
93F69411940695DE95E095DF972E972F97B997BB97FD97FE986098629863985F
98C198C29950994E9959994C994B99539A329A349A319A2C9A2A9A369A299A2E
9A389A2D9AC79ACA9AC69B109B129B119C0B9C089BF79C059C129BF89C400000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009C079C0E9C069C179C149C099D9F9D999DA49D9D9D929D989D909D9B9DA0
9D949D9C9DAA9D979DA19D9A9DA29DA89D9E9DA39DBF9DA99D969DA69DA79E99
9E9B9E9A9EE59EE49EE79EE69F309F2E9F5B9F609F5E9F5D9F599F91513A5139
5298529756C356BD56BE5B485B475DCB5DCF5EF161FD651B6B026AFC6B036AF8
6B0070437044704A7048704970457046721D721A7219737E7517766A77D0792D
7931792F7C547C537CF27E8A7E877E887E8B7E867E8D7F4D7FBB803081DD0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008618862A8626861F8623861C86198627862E862186208629861E86258829
881D881B88208824881C882B884A896D8969896E896B89FA8B798B788B458B7A
8B7B8D108D148DAF8E8E8E8C8F5E8F5B8F5D91469144914591B9943F943B9436
9429943D94309439942A9437942C9440943195E595E495E39735973A97BF97E1
986498C998C698C0995899569A399A3D9A469A449A429A419A3A9A3F9ACD9B15
9B179B189B169B3A9B529C2B9C1D9C1C9C2C9C239C289C299C249C219DB70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009DB69DBC9DC19DC79DCA9DCF9DBE9DC59DC39DBB9DB59DCE9DB99DBA9DAC
9DC89DB19DAD9DCC9DB39DCD9DB29E7A9E9C9EEB9EEE9EED9F1B9F189F1A9F31
9F4E9F659F649F924EB956C656C556CB59715B4B5B4C5DD55DD15EF265216520
652665226B0B6B086B096C0D7055705670577052721E721F72A9737F74D874D5
74D974D7766D76AD793579B47A707A717C577C5C7C597C5B7C5A7CF47CF17E91
7F4F7F8781DE826B863486358633862C86328636882C88288826882A88250000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000897189BF89BE89FB8B7E8B848B828B868B858B7F8D158E958E948E9A8E92
8E908E968E978F608F629147944C9450944A944B944F94479445944894499446
973F97E3986A986998CB9954995B9A4E9A539A549A4C9A4F9A489A4A9A499A52
9A509AD09B199B2B9B3B9B569B559C469C489C3F9C449C399C339C419C3C9C37
9C349C329C3D9C369DDB9DD29DDE9DDA9DCB9DD09DDC9DD19DDF9DE99DD99DD8
9DD69DF59DD59DDD9EB69EF09F359F339F329F429F6B9F959FA2513D52990000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000058E858E759725B4D5DD8882F5F4F62016203620465296525659666EB6B11
6B126B0F6BCA705B705A7222738273817383767077D47C677C667E95826C863A
86408639863C8631863B863E88308832882E883389768974897389FE8B8C8B8E
8B8B8B888C458D198E988F648F6391BC94629455945D9457945E97C497C59800
9A569A599B1E9B1F9B209C529C589C509C4A9C4D9C4B9C559C599C4C9C4E9DFB
9DF79DEF9DE39DEB9DF89DE49DF69DE19DEE9DE69DF29DF09DE29DEC9DF40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
70
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009DF39DE89DED9EC29ED09EF29EF39F069F1C9F389F379F369F439F4F9F71
9F709F6E9F6F56D356CD5B4E5C6D652D66ED66EE6B13705F7061705D70607223
74DB74E577D5793879B779B67C6A7E977F89826D8643883888378835884B8B94
8B958E9E8E9F8EA08E9D91BE91BD91C2946B9468946996E597469743974797C7
97E59A5E9AD59B599C639C679C669C629C5E9C609E029DFE9E079E039E069E05
9E009E019E099DFF9DFD9E049EA09F1E9F469F749F759F7656D4652E65B80000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
71
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B186B196B176B1A7062722672AA77D877D979397C697C6B7CF67E9A7E98
7E9B7E9981E081E18646864786488979897A897C897B89FF8B988B998EA58EA4
8EA3946E946D946F9471947397499872995F9C689C6E9C6D9E0B9E0D9E109E0F
9E129E119EA19EF59F099F479F789F7B9F7A9F79571E70667C6F883C8DB28EA6
91C394749478947694759A609B2E9C749C739C719C759E149E139EF69F0A9FA4
706870657CF7866A883E883D883F8B9E8C9C8EA98EC9974B9873987498CC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
72
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000996199AB9A649A669A679B249E159E179F4862076B1E7227864C8EA89482
948094819A699A689E19864B8B9F94839C799EB776759A6B9C7A9E1D7069706A
72299EA49F7E9F499F988AF68AFC8C6B8C6D8C938CF48E448E318E348E428E39
8E358F3B8F2F8F388F338FA88FA69075907490789072907C907A913491929320
933692F89333932F932292FC932B9304931A9310932693219315932E931995BB
96A796A896AA96D5970E97119716970D9713970F975B975C9766979898300000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
73
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009838983B9837982D9839982499109928991E991B9921991A99ED99E299F1
9AB89ABC9AFB9AED9B289B919D159D239D269D289D129D1B9ED89ED49F8D9F9C
512A511F5121513252F5568E5680569056855687568F58D558D358D158CE5B30
5B2A5B245B7A5C375C685DBC5DBA5DBD5DB85E6B5F4C5FBD61C961C261C761E6
61CB6232623464CE64CA64D864E064F064E664EC64F164E264ED6582658366D9
66D66A806A946A846AA26A9C6ADB6AA36A7E6A976A906AA06B5C6BAE6BDA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
74
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006C086FD86FF16FDF6FE06FDB6FE46FEB6FEF6F806FEC6FE16FE96FD56FEE
6FF071E771DF71EE71E671E571ED71EC71F471E0723572467370737274A974B0
74A674A876467642764C76EA77B377AA77B077AC77A777AD77EF78F778FA78F4
78EF790179A779AA7A577ABF7C077C0D7BFE7BF77C0C7BE07CE07CDC7CDE7CE2
7CDF7CD97CDD7E2E7E3E7E467E377E327E437E2B7E3D7E317E457E417E347E39
7E487E357E3F7E2F7F447FF37FFC807180728070806F807381C681C381BA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
75
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000081C281C081BF81BD81C981BE81E88209827185AA8584857E859C85918594
85AF859B858785A8858A85A6866787C087D187B387D287C687AB87BB87BA87C8
87CB893B893689448938893D89AC8B0E8B178B198B1B8B0A8B208B1D8B048B10
8C418C3F8C738CFA8CFD8CFC8CF88CFB8DA88E498E4B8E488E4A8F448F3E8F42
8F458F3F907F907D9084908190829080913991A3919E919C934D938293289375
934A9365934B9318937E936C935B9370935A935495CA95CB95CC95C895C60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
76
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000096B196B896D6971C971E97A097D3984698B699359A0199FF9BAE9BAB9BAA
9BAD9D3B9D3F9E8B9ECF9EDE9EDC9EDD9EDB9F3E9F4B53E2569556AE58D958D8
5B385F5E61E3623364F464F264FE650664FA64FB64F765B766DC67266AB36AAC
6AC36ABB6AB86AC26AAE6AAF6B5F6B786BAF7009700B6FFE70066FFA7011700F
71FB71FC71FE71F87377737574A774BF751576567658765277BD77BF77BB77BC
790E79AE7A617A627A607AC47AC57C2B7C277C2A7C1E7C237C217CE77E540000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
77
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007E557E5E7E5A7E617E527E597F487FF97FFB8077807681CD81CF820A85CF
85A985CD85D085C985B085BA85B987EF87EC87F287E0898689B289F48B288B39
8B2C8B2B8C508D058E598E638E668E648E5F8E558EC08F498F4D908790839088
91AB91AC91D09394938A939693A293B393AE93AC93B09398939A939795D495D6
95D095D596E296DC96D996DB96DE972497A397A697AD97F9984D984F984C984E
985398BA993E993F993D992E99A59A0E9AC19B039B069B4F9B4E9B4D9BCA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
78
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009BC99BFD9BC89BC09D519D5D9D609EE09F159F2C513356A556A858DE58DF
58E25BF59F905EEC61F261F761F661F56500650F66E066DD6AE56ADD6ADA6AD3
701B701F7028701A701D701570187206720D725872A27378737A74BD74CA74E3
75877586765F766177C7791979B17A6B7A697C3E7C3F7C387C3D7C377C407E6B
7E6D7E797E697E6A7E737F857FB67FB97FB881D885E985DD85EA85D585E485E5
85F787FB8805880D87F987FE8960895F8956895E8B418B5C8B588B498B5A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
79
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008B4E8B4F8B468B598D088D0A8E7C8E728E878E768E6C8E7A8E748F548F4E
8FAD908A908B91B191AE93E193D193DF93C393C893DC93DD93D693E293CD93D8
93E493D793E895DC96B496E3972A9727976197DC97FB985E9858985B98BC9945
99499A169A199B0D9BE89BE79BD69BDB9D899D619D729D6A9D6C9E929E979E93
9EB452F856B756B656B456BC58E45B405B435B7D5BF65DC961F861FA65186514
651966E667276AEC703E703070327210737B74CF766276657926792A792C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000792B7AC77AF67C4C7C437C4D7CEF7CF08FAE7E7D7E7C7E827F4C800081DA
826685FB85F9861185FA8606860B8607860A88148815896489BA89F88B708B6C
8B668B6F8B5F8B6B8D0F8D0D8E898E818E858E8291B491CB9418940393FD95E1
973098C49952995199A89A2B9A309A379A359C139C0D9E799EB59EE89F2F9F5F
9F639F615137513856C156C056C259145C6C5DCD61FC61FE651D651C659566E9
6AFB6B046AFA6BB2704C721B72A774D674D4766977D37C507E8F7E8C7FBC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008617862D861A882388228821881F896A896C89BD8B748B778B7D8D138E8A
8E8D8E8B8F5F8FAF91BA942E94339435943A94389432942B95E2973897399732
97FF9867986599579A459A439A409A3E9ACF9B549B519C2D9C259DAF9DB49DC2
9DB89E9D9EEF9F199F5C9F669F67513C513B56C856CA56C95B7F5DD45DD25F4E
61FF65246B0A6B6170517058738074E4758A766E766C79B37C607C5F807E807D
81DF8972896F89FC8B808D168D178E918E938F619148944494519452973D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000973E97C397C1986B99559A559A4D9AD29B1A9C499C319C3E9C3B9DD39DD7
9F349F6C9F6A9F9456CC5DD662006523652B652A66EC6B1074DA7ACA7C647C63
7C657E937E967E9481E28638863F88318B8A9090908F9463946094649768986F
995C9A5A9A5B9A579AD39AD49AD19C549C579C569DE59E9F9EF456D158E9652C
705E7671767277D77F507F888836883988628B938B928B9682778D1B91C0946A
97429748974497C698709A5F9B229B589C5F9DF99DFA9E7C9E7D9F079F770000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009F725EF36B1670637C6C7C6E883B89C08EA191C1947294709871995E9AD6
9B239ECC706477DA8B9A947797C99A629A657E9C8B9C8EAA91C5947D947E947C
9C779C789EF78C54947F9E1A72289A6A9B319E1B9E1E7C720000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted library/encoding/iso8859-11.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Encoding file: iso8859-11, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F
0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































Changes to library/encoding/iso8859-7.enc.

8
9
10
11
12
13
14
15
16
17
18
19
20
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A02018201900A320AC20AF00A600A700A800A9037A00AB00AC00AD00002015
00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000







|





8
9
10
11
12
13
14
15
16
17
18
19
20
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A02018201900A30000000000A600A700A800A9000000AB00AC00AD00002015
00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000

Changes to library/encoding/tis-620.enc.

Changes to library/http/http.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# http.tcl --
#
#	Client-side HTTP for GET, POST, and HEAD commands. These routines can
#	be used in untrusted code that uses the Safesock security policy.
#	These procedures use a callback interface to avoid using vwait, which
#	is not defined in the safe base.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.4
# Keep this in sync with pkgIndex.tcl and with the install directories in
# Makefiles
package provide http 2.7.15

namespace eval http {
    # Allow resourcing to not clobber existing data

    variable http
    if {![info exists http]} {
	array set http {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# http.tcl --
#
#	Client-side HTTP for GET, POST, and HEAD commands. These routines can
#	be used in untrusted code that uses the Safesock security policy.
#	These procedures use a callback interface to avoid using vwait, which
#	is not defined in the safe base.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.4
# Keep this in sync with pkgIndex.tcl and with the install directories in
# Makefiles
package provide http 2.7.14

namespace eval http {
    # Allow resourcing to not clobber existing data

    variable http
    if {![info exists http]} {
	array set http {
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
    if {$major eq "text"} {
	return false
    }
    # There's a bunch of XML-as-application-format things about. See RFC 3023
    # and so on.
    if {$major eq "application"} {
	set minor [string trimright $minor]
	if {$minor in {"json" "xml" "xml-external-parsed-entity" "xml-dtd"}} {
	    return false
	}
    }
    # Not just application/foobar+xml but also image/svg+xml, so let us not
    # restrict things for now...
    if {[string match "*+xml" $minor]} {
	return false







|







1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
    if {$major eq "text"} {
	return false
    }
    # There's a bunch of XML-as-application-format things about. See RFC 3023
    # and so on.
    if {$major eq "application"} {
	set minor [string trimright $minor]
	if {$minor in {"xml" "xml-external-parsed-entity" "xml-dtd"}} {
	    return false
	}
    }
    # Not just application/foobar+xml but also image/svg+xml, so let us not
    # restrict things for now...
    if {[string match "*+xml" $minor]} {
	return false
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
	set state(status) eof
    } else {
	set state(status) ok
    }

    if {($state(coding) eq "gzip") && [string length $state(body)] > 0} {
        if {[catch {
	    if {[package vsatisfies [package provide Tcl] 8.6]} {
		# The zlib integration into 8.6 includes proper gzip support
		set state(body) [zlib gunzip $state(body)]
	    } else {
		set state(body) [Gunzip $state(body)]
	    }
        } err]} then {
	    return [Finish $token $err]







|







1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
	set state(status) eof
    } else {
	set state(status) ok
    }

    if {($state(coding) eq "gzip") && [string length $state(body)] > 0} {
        if {[catch {
	    if {[package vsatisfies [package present Tcl] 8.6]} {
		# The zlib integration into 8.6 includes proper gzip support
		set state(body) [zlib gunzip $state(body)]
	    } else {
		set state(body) [Gunzip $state(body)]
	    }
        } err]} then {
	    return [Finish $token $err]

Changes to library/http/pkgIndex.tcl.

1
2
3
4
# Tcl package index file, version 1.1

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded http 2.7.15 [list tclPkgSetup $dir http 2.7.15 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]



|
1
2
3
4
# Tcl package index file, version 1.1

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded http 2.7.14 [list tclPkgSetup $dir http 2.7.14 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]

Changes to library/http1.0/http.tcl.

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

# do x-www-urlencoded character mapping
# The spec says: "non-alphanumeric characters are replaced by '%HH'"
# 1 leave alphanumerics characters alone
# 2 Convert every other character to an array lookup
# 3 Escape constructs that are "special" to the tcl parser
# 4 "subst" the result, doing all the array substitutions

 proc httpMapReply {string} {
    global httpFormMap
    set alphanumeric	a-zA-Z0-9
    if {![info exists httpFormMap]} {

	for {set i 1} {$i <= 256} {incr i} {
	    set c [format %c $i]
	    if {![string match \[$alphanumeric\] $c]} {
		set httpFormMap($c) %[format %.2x $i]
	    }
	}
	# These are handled specially
	array set httpFormMap {
	    " " +   \n %0d%0a
	}
    }
    regsub -all \[^$alphanumeric\] $string {$httpFormMap(&)} string
    regsub -all \n $string {\\n} string
    regsub -all \t $string {\\t} string
    regsub -all {[][{})\\]\)} $string {\\&} string
    return [subst $string]
}

# Default proxy filter.
 proc httpProxyRequired {host} {
    global http
    if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
	if {![info exists http(-proxyport)] || ![string length $http(-proxyport)]} {
	    set http(-proxyport) 8080
	}
	return [list $http(-proxyhost) $http(-proxyport)]
    } else {
	return {}
    }
}







|




|


















|











335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

# do x-www-urlencoded character mapping
# The spec says: "non-alphanumeric characters are replaced by '%HH'"
# 1 leave alphanumerics characters alone
# 2 Convert every other character to an array lookup
# 3 Escape constructs that are "special" to the tcl parser
# 4 "subst" the result, doing all the array substitutions
 
 proc httpMapReply {string} {
    global httpFormMap
    set alphanumeric	a-zA-Z0-9
    if {![info exists httpFormMap]} {
	 
	for {set i 1} {$i <= 256} {incr i} {
	    set c [format %c $i]
	    if {![string match \[$alphanumeric\] $c]} {
		set httpFormMap($c) %[format %.2x $i]
	    }
	}
	# These are handled specially
	array set httpFormMap {
	    " " +   \n %0d%0a
	}
    }
    regsub -all \[^$alphanumeric\] $string {$httpFormMap(&)} string
    regsub -all \n $string {\\n} string
    regsub -all \t $string {\\t} string
    regsub -all {[][{})\\]\)} $string {\\&} string
    return [subst $string]
}

# Default proxy filter. 
 proc httpProxyRequired {host} {
    global http
    if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
	if {![info exists http(-proxyport)] || ![string length $http(-proxyport)]} {
	    set http(-proxyport) 8080
	}
	return [list $http(-proxyhost) $http(-proxyport)]
    } else {
	return {}
    }
}

Changes to library/init.tcl.

53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
	}
    }
    set Dir [file join [file dirname [file dirname \
	    [info nameofexecutable]]] lib]
    if {$Dir ni $::auto_path} {
	lappend ::auto_path $Dir
    }
    if {[info exists ::tcl_pkgPath]} { catch {
	foreach Dir $::tcl_pkgPath {
	    if {$Dir ni $::auto_path} {
		lappend ::auto_path $Dir
	    }
	}
    }}


    if {![interp issafe]} {
        variable Path [encoding dirs]
        set Dir [file join $::tcl_library encoding]
        if {$Dir ni $Path} {
	    lappend Path $Dir
	    encoding dirs $Path







|





<
>







53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
	}
    }
    set Dir [file join [file dirname [file dirname \
	    [info nameofexecutable]]] lib]
    if {$Dir ni $::auto_path} {
	lappend ::auto_path $Dir
    }
    catch {
	foreach Dir $::tcl_pkgPath {
	    if {$Dir ni $::auto_path} {
		lappend ::auto_path $Dir
	    }
	}

    }

    if {![interp issafe]} {
        variable Path [encoding dirs]
        set Dir [file join $::tcl_library encoding]
        if {$Dir ni $Path} {
	    lappend Path $Dir
	    encoding dirs $Path
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
	set f ""
	if {$issafe} {
	    catch {source [file join $dir tclIndex]}
	} elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
	    continue
	} else {
	    set error [catch {
		fconfigure $f -eofchar "\032 {}"
		set id [gets $f]
		if {$id eq "# Tcl autoload index file, version 2.0"} {
		    eval [read $f]
		} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
		    while {[gets $f line] >= 0} {
			if {([string index $line 0] eq "#") \
				|| ([llength $line] != 2)} {







<







497
498
499
500
501
502
503

504
505
506
507
508
509
510
	set f ""
	if {$issafe} {
	    catch {source [file join $dir tclIndex]}
	} elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
	    continue
	} else {
	    set error [catch {

		set id [gets $f]
		if {$id eq "# Tcl autoload index file, version 2.0"} {
		    eval [read $f]
		} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
		    while {[gets $f line] >= 0} {
			if {([string index $line 0] eq "#") \
				|| ([llength $line] != 2)} {
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
#
# Arguments:
# name -			Name of a command.

if {$tcl_platform(platform) eq "windows"} {
# Windows version.
#
# Note that file executable doesn't work under Windows, so we have to
# look for files with .exe, .com, or .bat extensions.  Also, the path
# may be in the Path or PATH environment variables, and path
# components are separated with semicolons, not colons as under Unix.
#
proc auto_execok name {
    global auto_execs env tcl_platform

    if {[info exists auto_execs($name)]} {
	return $auto_execs($name)
    }
    set auto_execs($name) ""

    set shellBuiltins [list assoc cls copy date del dir echo erase exit ftype \
	    md mkdir mklink move rd ren rename rmdir start time type ver vol]
    if {[info exists env(PATHEXT)]} {
	# Add an initial ; to have the {} extension check first.
	set execExtensions [split ";$env(PATHEXT)" ";"]
    } else {
	set execExtensions [list {} .com .exe .bat .cmd]
    }








|












|
|







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
#
# Arguments:
# name -			Name of a command.

if {$tcl_platform(platform) eq "windows"} {
# Windows version.
#
# Note that info executable doesn't work under Windows, so we have to
# look for files with .exe, .com, or .bat extensions.  Also, the path
# may be in the Path or PATH environment variables, and path
# components are separated with semicolons, not colons as under Unix.
#
proc auto_execok name {
    global auto_execs env tcl_platform

    if {[info exists auto_execs($name)]} {
	return $auto_execs($name)
    }
    set auto_execs($name) ""

    set shellBuiltins [list cls copy date del dir echo erase md mkdir \
	    mklink rd ren rename rmdir start time type ver vol]
    if {[info exists env(PATHEXT)]} {
	# Add an initial ; to have the {} extension check first.
	set execExtensions [split ";$env(PATHEXT)" ";"]
    } else {
	set execExtensions [list {} .com .exe .bat .cmd]
    }

677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    set path "[file dirname [info nameof]];.;"
    if {[info exists env(SystemRoot)]} {
	set windir $env(SystemRoot)
    } elseif {[info exists env(WINDIR)]} {
	set windir $env(WINDIR)
    }
    if {[info exists windir]} {
	if {$tcl_platform(os) eq "Windows NT"} {
	    append path "$windir/system32;"
	}
	append path "$windir/system;$windir;"







|
<
<







676
677
678
679
680
681
682
683


684
685
686
687
688
689
690
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    set path "[file dirname [info nameof]];.;"
    if {[info exists env(WINDIR)]} {


	set windir $env(WINDIR)
    }
    if {[info exists windir]} {
	if {$tcl_platform(os) eq "Windows NT"} {
	    append path "$windir/system32;"
	}
	append path "$windir/system;$windir;"
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
		if {[file tail $s] ni {. ..}} {
		    return -code error "error $action \"$src\" to\
		      \"$dest\": file already exists"
		}
	    }
	}
    } else {
	if {[string first $nsrc $ndest] >= 0} {
	    set srclen [expr {[llength [file split $nsrc]] - 1}]
	    set ndest [lindex [file split $ndest] $srclen]
	    if {$ndest eq [file tail $nsrc]} {
		return -code error "error $action \"$src\" to\
		  \"$dest\": trying to rename a volume or move a directory\
		  into itself"
	    }







|







798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
		if {[file tail $s] ni {. ..}} {
		    return -code error "error $action \"$src\" to\
		      \"$dest\": file already exists"
		}
	    }
	}
    } else {
	if {[string first $nsrc $ndest] != -1} {
	    set srclen [expr {[llength [file split $nsrc]] - 1}]
	    set ndest [lindex [file split $ndest] $srclen]
	    if {$ndest eq [file tail $nsrc]} {
		return -code error "error $action \"$src\" to\
		  \"$dest\": trying to rename a volume or move a directory\
		  into itself"
	    }

Changes to library/msgs/ja.msg.

36
37
38
39
40
41
42
43
44
    ::msgcat::mcset ja DATE_FORMAT "%Y/%m/%d"
    ::msgcat::mcset ja TIME_FORMAT "%k:%M:%S"
    ::msgcat::mcset ja TIME_FORMAT_12 "%P %I:%M:%S"
    ::msgcat::mcset ja DATE_TIME_FORMAT "%Y/%m/%d %k:%M:%S %z"
    ::msgcat::mcset ja LOCALE_DATE_FORMAT "%EY\u5e74%m\u6708%d\u65e5"
    ::msgcat::mcset ja LOCALE_TIME_FORMAT "%H\u6642%M\u5206%S\u79d2"
    ::msgcat::mcset ja LOCALE_DATE_TIME_FORMAT "%EY\u5e74%m\u6708%d\u65e5 (%a) %H\u6642%M\u5206%S\u79d2 %z"
    ::msgcat::mcset ja LOCALE_ERAS "{-9223372036854775808 \u897f\u66a6 0} {-3061011600 \u660e\u6cbb 1867} {-1812186000 \u5927\u6b63 1911} {-1357635600 \u662d\u548c 1925} {600220800 \u5e73\u6210 1988} {1556668800 \u4ee4\u548c 2018}"
}







|

36
37
38
39
40
41
42
43
44
    ::msgcat::mcset ja DATE_FORMAT "%Y/%m/%d"
    ::msgcat::mcset ja TIME_FORMAT "%k:%M:%S"
    ::msgcat::mcset ja TIME_FORMAT_12 "%P %I:%M:%S"
    ::msgcat::mcset ja DATE_TIME_FORMAT "%Y/%m/%d %k:%M:%S %z"
    ::msgcat::mcset ja LOCALE_DATE_FORMAT "%EY\u5e74%m\u6708%d\u65e5"
    ::msgcat::mcset ja LOCALE_TIME_FORMAT "%H\u6642%M\u5206%S\u79d2"
    ::msgcat::mcset ja LOCALE_DATE_TIME_FORMAT "%EY\u5e74%m\u6708%d\u65e5 (%a) %H\u6642%M\u5206%S\u79d2 %z"
    ::msgcat::mcset ja LOCALE_ERAS "\u007b-9223372036854775808 \u897f\u66a6 0\u007d \u007b-3061011600 \u660e\u6cbb 1867\u007d \u007b-1812186000 \u5927\u6b63 1911\u007d \u007b-1357635600 \u662d\u548c 1925\u007d \u007b600220800 \u5e73\u6210 1988\u007d"
}

Changes to library/opt/optparse.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# optparse.tcl --
#
#       (private) Option parsing package
#       Primarily used internally by the safe:: code.
#
#	WARNING: This code will go away in a future release
#	of Tcl.  It is NOT supported and you should not rely
#	on it.  If your code does rely on this package you
#	may directly incorporate this code into your application.

package require Tcl 8.5-
# When this version number changes, update the pkgIndex.tcl file
# and the install directory in the Makefiles.
package provide opt 0.4.7

namespace eval ::tcl {

    # Exported APIs
    namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \
             OptProc OptProcArgGiven OptParse \
	     Lempty Lget \










|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# optparse.tcl --
#
#       (private) Option parsing package
#       Primarily used internally by the safe:: code.
#
#	WARNING: This code will go away in a future release
#	of Tcl.  It is NOT supported and you should not rely
#	on it.  If your code does rely on this package you
#	may directly incorporate this code into your application.

package require Tcl 8.2
# When this version number changes, update the pkgIndex.tcl file
# and the install directory in the Makefiles.
package provide opt 0.4.5

namespace eval ::tcl {

    # Exported APIs
    namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \
             OptProc OptProcArgGiven OptParse \
	     Lempty Lget \
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

	# Defines ::tcl::OptParseTest as a test proc with parsed arguments
	# (can't be defined before the code below is loaded (before "OptProc"))

	# Every OptProc give usage information on "procname -help".
	# Try "tcl::OptParseTest -help" and "tcl::OptParseTest -a" and
	# then other arguments.
	#
	# example of 'valid' call:
	# ::tcl::OptParseTest save -4 -pr 23 -libsok SybTcl\
	#		-nostatics false ch1
	OptProc OptParseTest {
            {subcommand -choice {save print} "sub command"}
            {arg1 3 "some number"}
            {-aflag}







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

	# Defines ::tcl::OptParseTest as a test proc with parsed arguments
	# (can't be defined before the code below is loaded (before "OptProc"))

	# Every OptProc give usage information on "procname -help".
	# Try "tcl::OptParseTest -help" and "tcl::OptParseTest -a" and
	# then other arguments.
	# 
	# example of 'valid' call:
	# ::tcl::OptParseTest save -4 -pr 23 -libsok SybTcl\
	#		-nostatics false ch1
	OptProc OptParseTest {
            {subcommand -choice {save print} "sub command"}
            {arg1 3 "some number"}
            {-aflag}
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
	    }
	}
    }

###################  No User serviceable part below ! ###############

    # Array storing the parsed descriptions
    variable OptDesc
    array set OptDesc {}
    # Next potentially free key id (numeric)
    variable OptDescN 0

# Inside algorithm/mechanism description:
# (not for the faint hearted ;-)
#
# The argument description is parsed into a "program tree"
# It is called a "program" because it is the program used by
# the state machine interpreter that use that program to
# actually parse the arguments at run time.
#
# The general structure of a "program" is
# notation (pseudo bnf like)
#    name :== definition        defines "name" as being "definition"
#    { x y z }                  means list of x, y, and z
#    x*                         means x repeated 0 or more time
#    x+                         means "x x*"
#    x?                         means optionally x
#    x | y                      means x or y
#    "cccc"                     means the literal string
#
#    program        :== { programCounter programStep* }







|
|

|











|
|







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
	    }
	}
    }

###################  No User serviceable part below ! ###############

    # Array storing the parsed descriptions
    variable OptDesc;
    array set OptDesc {};
    # Next potentially free key id (numeric)
    variable OptDescN 0;

# Inside algorithm/mechanism description:
# (not for the faint hearted ;-)
#
# The argument description is parsed into a "program tree"
# It is called a "program" because it is the program used by
# the state machine interpreter that use that program to
# actually parse the arguments at run time.
#
# The general structure of a "program" is
# notation (pseudo bnf like)
#    name :== definition        defines "name" as being "definition" 
#    { x y z }                  means list of x, y, and z  
#    x*                         means x repeated 0 or more time
#    x+                         means "x x*"
#    x?                         means optionally x
#    x | y                      means x or y
#    "cccc"                     means the literal string
#
#    program        :== { programCounter programStep* }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#   llength [lindex $program 0] >= 2
# while
#   llength [lindex $singleStep 0] == 1
# )
#
# And for this application:
#
#    singleStep     :== { instruction varname {hasBeenSet currentValue} type
#                         typeArgs help }
#    instruction    :== "flags" | "value"
#    type           :== knowType | anyword
#    knowType       :== "string" | "int" | "boolean" | "boolflag" | "float"
#                       | "choice"
#
# for type "choice" typeArgs is a list of possible choices, the first one







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#   llength [lindex $program 0] >= 2
# while
#   llength [lindex $singleStep 0] == 1
# )
#
# And for this application:
#
#    singleStep     :== { instruction varname {hasBeenSet currentValue} type 
#                         typeArgs help }
#    instruction    :== "flags" | "value"
#    type           :== knowType | anyword
#    knowType       :== "string" | "int" | "boolean" | "boolflag" | "float"
#                       | "choice"
#
# for type "choice" typeArgs is a list of possible choices, the first one
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
# string rep might be calculated at great exense. to be checked.

#
# Parse a given description and saves it here under the given key
# generate a unused keyid if not given
#
proc ::tcl::OptKeyRegister {desc {key ""}} {
    variable OptDesc
    variable OptDescN
    if {[string equal $key ""]} {
        # in case a key given to us as a parameter was a number
        while {[info exists OptDesc($OptDescN)]} {incr OptDescN}
        set key $OptDescN
        incr OptDescN
    }
    # program counter
    set program [list [list "P" 1]]

    # are we processing flags (which makes a single program step)
    set inflags 0

    set state {}

    # flag used to detect that we just have a single (flags set) subprogram.
    set empty 1

    foreach item $desc {
	if {$state == "args"} {
	    # more items after 'args'...
	    return -code error "'args' special argument must be the last one"
	}
        set res [OptNormalizeOne $item]
        set state [lindex $res 0]
        if {$inflags} {
            if {$state == "flags"} {
		# add to 'subprogram'
                lappend flagsprg $res
            } else {
                # put in the flags
                # structure for flag programs items is a list of
                # {subprgcounter {prg flag 1} {prg flag 2} {...}}
                lappend program $flagsprg
                # put the other regular stuff
                lappend program $res
		set inflags 0
		set empty 0
            }
        } else {
           if {$state == "flags"} {
               set inflags 1
               # sub program counter + first sub program
               set flagsprg [list [list "P" 1] $res]
           } else {
               lappend program $res
               set empty 0
           }
       }
   }
   if {$inflags} {
       if {$empty} {
	   # We just have the subprogram, optimize and remove
	   # unneeded level:
	   set program $flagsprg
       } else {
	   lappend program $flagsprg
       }
   }

   set OptDesc($key) $program

   return $key
}

#
# Free the storage for that given key
#
proc ::tcl::OptKeyDelete {key} {
    variable OptDesc
    unset OptDesc($key)
}

    # Get the parsed description stored under the given key.
    proc OptKeyGetDesc {descKey} {
        variable OptDesc
        if {![info exists OptDesc($descKey)]} {
            return -code error "Unknown option description key \"$descKey\""
        }
        set OptDesc($descKey)
    }

# Parse entry point for ppl who don't want to register with a key,
# for instance because the description changes dynamically.
#  (otherwise one should really use OptKeyRegister once + OptKeyParse
#   as it is way faster or simply OptProc which does it all)
# Assign a temporary key, call OptKeyParse and then free the storage
proc ::tcl::OptParse {desc arglist} {
    set tempkey [OptKeyRegister $desc]
    set ret [catch {uplevel 1 [list ::tcl::OptKeyParse $tempkey $arglist]} res]
    OptKeyDelete $tempkey
    return -code $ret $res
}

# Helper function, replacement for proc that both
# register the description under a key which is the name of the proc
# (and thus unique to that code)
# and add a first line to the code to call the OptKeyParse proc
# Stores the list of variables that have been actually given by the user
# (the other will be sets to their default value)
# into local variable named "Args".
proc ::tcl::OptProc {name desc body} {
    set namespace [uplevel 1 [list ::namespace current]]
    if {[string match "::*" $name] || [string equal $namespace "::"]} {
        # absolute name or global namespace, name is the key
        set key $name
    } else {
        # we are relative to some non top level namespace:
        set key "${namespace}::${name}"
    }
    OptKeyRegister $desc $key
    uplevel 1 [list ::proc $name args "set Args \[::tcl::OptKeyParse $key \$args\]\n$body"]
    return $key
}
# Check that a argument has been given
# assumes that "OptProc" has been used as it will check in "Args" list
proc ::tcl::OptProcArgGiven {argname} {
    upvar Args alist
    expr {[lsearch $alist $argname] >=0}
}

    #######
    # Programs/Descriptions manipulation

    # Return the instruction word/list of a given step/(sub)program
    proc OptInstr {lst} {
	lindex $lst 0
    }
    # Is a (sub) program or a plain instruction ?
    proc OptIsPrg {lst} {
	expr {[llength [OptInstr $lst]]>=2}
    }
    # Is this instruction a program counter or a real instr
    proc OptIsCounter {item} {
	expr {[lindex $item 0]=="P"}
    }
    # Current program counter (2nd word of first word)
    proc OptGetPrgCounter {lst} {
	Lget $lst {0 1}
    }
    # Current program counter (2nd word of first word)
    proc OptSetPrgCounter {lstName newValue} {
	upvar $lstName lst
	set lst [lreplace $lst 0 0 [concat "P" $newValue]]
    }
    # returns a list of currently selected items.
    proc OptSelection {lst} {
	set res {}
	foreach idx [lrange [lindex $lst 0] 1 end] {
	    lappend res [Lget $lst $idx]
	}
	return $res
    }

    # Advance to next description
    proc OptNextDesc {descName} {
        uplevel 1 [list Lvarincr $descName {0 1}]
    }

    # Get the current description, eventually descend
    proc OptCurDesc {descriptions} {
        lindex $descriptions [OptGetPrgCounter $descriptions]
    }
    # get the current description, eventually descend
    # through sub programs as needed.
    proc OptCurDescFinal {descriptions} {
        set item [OptCurDesc $descriptions]
	# Descend untill we get the actual item and not a sub program
        while {[OptIsPrg $item]} {
            set item [OptCurDesc $item]
        }
	return $item
    }
    # Current final instruction adress
    proc OptCurAddr {descriptions {start {}}} {
	set adress [OptGetPrgCounter $descriptions]
	lappend start $adress
	set item [lindex $descriptions $adress]
	if {[OptIsPrg $item]} {
	    return [OptCurAddr $item $start]
	} else {
	    return $start
	}
    }
    # Set the value field of the current instruction
    proc OptCurSetValue {descriptionsName value} {
	upvar $descriptionsName descriptions
	# get the current item full adress
        set adress [OptCurAddr $descriptions]
	# use the 3th field of the item  (see OptValue / OptNewInst)
	lappend adress 2
	Lvarset descriptions $adress [list 1 $value]
	#                                  ^hasBeenSet flag
    }

    # empty state means done/paste the end of the program
    proc OptState {item} {
        lindex $item 0
    }

    # current state
    proc OptCurState {descriptions} {
        OptState [OptCurDesc $descriptions]
    }

    #######
    # Arguments manipulation

    # Returns the argument that has to be processed now
    proc OptCurrentArg {lst} {
        lindex $lst 0
    }
    # Advance to next argument
    proc OptNextArg {argsName} {
        uplevel 1 [list Lvarpop1 $argsName]
    }
    #######





    # Loop over all descriptions, calling OptDoOne which will
    # eventually eat all the arguments.
    proc OptDoAll {descriptionsName argumentsName} {
	upvar $descriptionsName descriptions
	upvar $argumentsName arguments
#	puts "entered DoAll"
	# Nb: the places where "state" can be set are tricky to figure
	#     because DoOne sets the state to flagsValue and return -continue
	#     when needed...
	set state [OptCurState $descriptions]
	# We'll exit the loop in "OptDoOne" or when state is empty.
        while 1 {
	    set curitem [OptCurDesc $descriptions]
	    # Do subprograms if needed, call ourselves on the sub branch
	    while {[OptIsPrg $curitem]} {
		OptDoAll curitem arguments
#		puts "done DoAll sub"
		# Insert back the results in current tree
		Lvarset1nc descriptions [OptGetPrgCounter $descriptions]\
			$curitem
		OptNextDesc descriptions
		set curitem [OptCurDesc $descriptions]
                set state [OptCurState $descriptions]
	    }
#           puts "state = \"$state\" - arguments=($arguments)"
	    if {[Lempty $state]} {
		# Nothing left to do, we are done in this branch:
		break
	    }
	    # The following statement can make us terminate/continue
	    # as it use return -code {break, continue, return and error}
	    # codes
            OptDoOne descriptions state arguments
	    # If we are here, no special return code where issued,
	    # we'll step to next instruction :
#           puts "new state  = \"$state\""
	    OptNextDesc descriptions
	    set state [OptCurState $descriptions]
        }
    }

    # Process one step for the state machine,
    # eventually consuming the current argument.
    proc OptDoOne {descriptionsName stateName argumentsName} {
        upvar $argumentsName arguments
        upvar $descriptionsName descriptions
	upvar $stateName state

	# the special state/instruction "args" eats all
	# the remaining args (if any)
	if {($state == "args")} {
	    if {![Lempty $arguments]} {
		# If there is no additional arguments, leave the default value
		# in.
		OptCurSetValue descriptions $arguments
		set arguments {}
	    }
#            puts "breaking out ('args' state: consuming every reminding args)"
	    return -code break
	}

	if {[Lempty $arguments]} {
	    if {$state == "flags"} {
		# no argument and no flags : we're done
#                puts "returning to previous (sub)prg (no more args)"
		return -code return
	    } elseif {$state == "optValue"} {
		set state next; # not used, for debug only
		# go to next state
		return
	    } else {
		return -code error [OptMissingValue $descriptions]
	    }
	} else {
	    set arg [OptCurrentArg $arguments]
	}

        switch $state {
            flags {
                # A non-dash argument terminates the options, as does --

                # Still a flag ?
                if {![OptIsFlag $arg]} {
                    # don't consume the argument, return to previous prg
                    return -code return
                }
                # consume the flag
                OptNextArg arguments
                if {[string equal "--" $arg]} {
                    # return from 'flags' state
                    return -code return
                }

                set hits [OptHits descriptions $arg]
                if {$hits > 1} {
                    return -code error [OptAmbigous $descriptions $arg]
                } elseif {$hits == 0} {
                    return -code error [OptFlagUsage $descriptions $arg]
                }
		set item [OptCurDesc $descriptions]
                if {[OptNeedValue $item]} {
		    # we need a value, next state is
		    set state flagValue
                } else {
                    OptCurSetValue descriptions 1
                }
		# continue
		return -code continue
            }
	    flagValue -
	    value {
		set item [OptCurDesc $descriptions]
                # Test the values against their required type
		if {[catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    return -code error [OptBadValue $item $arg $val]
		}
                # consume the value
                OptNextArg arguments
		# set the value
		OptCurSetValue descriptions $val
		# go to next state
		if {$state == "flagValue"} {
		    set state flags
		    return -code continue
		} else {
		    set state next; # not used, for debug only
		    return ; # will go on next step
		}
	    }
	    optValue {
		set item [OptCurDesc $descriptions]
                # Test the values against their required type
		if {![catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    # right type, so :
		    # consume the value
		    OptNextArg arguments
		    # set the value
		    OptCurSetValue descriptions $val
		}
		# go to next state
		set state next; # not used, for debug only
		return ; # will go on next step
	    }
        }
	# If we reach this point: an unknown
	# state as been entered !
	return -code error "Bug! unknown state in DoOne \"$state\"\
		(prg counter [OptGetPrgCounter $descriptions]:\
			[OptCurDesc $descriptions])"
    }

# Parse the options given the key to previously registered description
# and arguments list
proc ::tcl::OptKeyParse {descKey arglist} {

    set desc [OptKeyGetDesc $descKey]

    # make sure -help always give usage
    if {[string equal -nocase "-help" $arglist]} {
	return -code error [OptError "Usage information:" $desc 1]
    }

    OptDoAll desc arglist

    if {![Lempty $arglist]} {
	return -code error [OptTooManyArgs $desc $arglist]
    }

    # Analyse the result
    # Walk through the tree:
    OptTreeVars $desc "#[expr {[info level]-1}]"
}

    # determine string length for nice tabulated output
    proc OptTreeVars {desc level {vnamesLst {}}} {
	foreach item $desc {
	    if {[OptIsCounter $item]} continue
	    if {[OptIsPrg $item]} {
		set vnamesLst [OptTreeVars $item $level $vnamesLst]
	    } else {
		set vname [OptVarName $item]
		upvar $level $vname var
		if {[OptHasBeenSet $item]} {
#		    puts "adding $vname"
		    # lets use the input name for the returned list
		    # it is more usefull, for instance you can check that
		    # no flags at all was given with expr
		    # {![string match "*-*" $Args]}
		    lappend vnamesLst [OptName $item]
		    set var [OptValue $item]
		} else {
		    set var [OptDefaultValue $item]
		}
	    }
	}
	return $vnamesLst
    }


# Check the type of a value
# and emit an error if arg is not of the correct type
# otherwise returns the canonical value of that arg (ie 0/1 for booleans)
proc ::tcl::OptCheckType {arg type {typeArgs ""}} {
#    puts "checking '$arg' against '$type' ($typeArgs)"

    # only types "any", "choice", and numbers can have leading "-"

    switch -exact -- $type {
        int {
            if {![string is integer -strict $arg]} {
                error "not an integer"
            }
	    return $arg
        }
        float {
            return [expr {double($arg)}]
        }
	script -
        list {
	    # if llength fail : malformed list
            if {[llength $arg]==0 && [OptIsFlag $arg]} {
		error "no values with leading -"
	    }
	    return $arg
        }
        boolean {
	    if {![string is boolean -strict $arg]} {
		error "non canonic boolean"
            }
	    # convert true/false because expr/if is broken with "!,...
	    return [expr {$arg ? 1 : 0}]
        }
        choice {
            if {[lsearch -exact $typeArgs $arg] < 0} {
                error "invalid choice"
            }
	    return $arg
        }
	any {
	    return $arg
	}
	string -
	default {
            if {[OptIsFlag $arg]} {
                error "no values with leading -"
            }
	    return $arg
        }
    }
    return neverReached
}

    # internal utilities

    # returns the number of flags matching the given arg
    # sets the (local) prg counter to the list of matches
    proc OptHits {descName arg} {
        upvar $descName desc
        set hits 0
        set hitems {}
	set i 1

	set larg [string tolower $arg]
	set len  [string length $larg]
	set last [expr {$len-1}]

        foreach item [lrange $desc 1 end] {
            set flag [OptName $item]
	    # lets try to match case insensitively
	    # (string length ought to be cheap)
	    set lflag [string tolower $flag]
	    if {$len == [string length $lflag]} {
		if {[string equal $larg $lflag]} {
		    # Exact match case
		    OptSetPrgCounter desc $i
		    return 1
		}
	    } elseif {[string equal $larg [string range $lflag 0 $last]]} {
		lappend hitems $i
		incr hits
            }
	    incr i
        }
	if {$hits} {
	    OptSetPrgCounter desc $hitems
	}
        return $hits
    }

    # Extract fields from the list structure:

    proc OptName {item} {
        lindex $item 1
    }
    proc OptHasBeenSet {item} {
	Lget $item {2 0}
    }
    proc OptValue {item} {
	Lget $item {2 1}
    }

    proc OptIsFlag {name} {
        string match "-*" $name
    }
    proc OptIsOpt {name} {
        string match {\?*} $name
    }
    proc OptVarName {item} {
        set name [OptName $item]
        if {[OptIsFlag $name]} {
            return [string range $name 1 end]
        } elseif {[OptIsOpt $name]} {
	    return [string trim $name "?"]
	} else {
            return $name
        }
    }
    proc OptType {item} {
        lindex $item 3
    }
    proc OptTypeArgs {item} {
        lindex $item 4







|
|



|
|


|


|

|


|




|

|
|



|




|

|
|
|



|

|

|
|







|

|



|

|






|
|




|

|

|








|
|
|
|










|


|


|

|
|
|




|








|















|
|



|

|

|




|




|




|


|

|



|
|
|

|

|






|


|







|


|







|



|











|
|



|


|



|
|

|
|
|
|

|


|




|


|
|
|






|
|
|







|
|


|





|
|



|

|


|









|


|


|


|





|


|

|


|



|






|

|



|






|





|

|










|






|



|


|


|

|


|





|

|

|







|
|

|











|








|










|












|


|









|







|


|

|
|
|





|



|
|


|
|

|


|







|


|


|



|


|


|

|

|

|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
# string rep might be calculated at great exense. to be checked.

#
# Parse a given description and saves it here under the given key
# generate a unused keyid if not given
#
proc ::tcl::OptKeyRegister {desc {key ""}} {
    variable OptDesc;
    variable OptDescN;
    if {[string equal $key ""]} {
        # in case a key given to us as a parameter was a number
        while {[info exists OptDesc($OptDescN)]} {incr OptDescN}
        set key $OptDescN;
        incr OptDescN;
    }
    # program counter
    set program [list [list "P" 1]];

    # are we processing flags (which makes a single program step)
    set inflags 0;

    set state {};

    # flag used to detect that we just have a single (flags set) subprogram.
    set empty 1;

    foreach item $desc {
	if {$state == "args"} {
	    # more items after 'args'...
	    return -code error "'args' special argument must be the last one";
	}
        set res [OptNormalizeOne $item];
        set state [lindex $res 0];
        if {$inflags} {
            if {$state == "flags"} {
		# add to 'subprogram'
                lappend flagsprg $res;
            } else {
                # put in the flags
                # structure for flag programs items is a list of
                # {subprgcounter {prg flag 1} {prg flag 2} {...}}
                lappend program $flagsprg;
                # put the other regular stuff
                lappend program $res;
		set inflags 0;
		set empty 0;
            }
        } else {
           if {$state == "flags"} {
               set inflags 1;
               # sub program counter + first sub program
               set flagsprg [list [list "P" 1] $res];
           } else {
               lappend program $res;
               set empty 0;
           }
       }
   }
   if {$inflags} {
       if {$empty} {
	   # We just have the subprogram, optimize and remove
	   # unneeded level:
	   set program $flagsprg;
       } else {
	   lappend program $flagsprg;
       }
   }

   set OptDesc($key) $program;

   return $key;
}

#
# Free the storage for that given key
#
proc ::tcl::OptKeyDelete {key} {
    variable OptDesc;
    unset OptDesc($key);
}

    # Get the parsed description stored under the given key.
    proc OptKeyGetDesc {descKey} {
        variable OptDesc;
        if {![info exists OptDesc($descKey)]} {
            return -code error "Unknown option description key \"$descKey\"";
        }
        set OptDesc($descKey);
    }

# Parse entry point for ppl who don't want to register with a key,
# for instance because the description changes dynamically.
#  (otherwise one should really use OptKeyRegister once + OptKeyParse
#   as it is way faster or simply OptProc which does it all)
# Assign a temporary key, call OptKeyParse and then free the storage
proc ::tcl::OptParse {desc arglist} {
    set tempkey [OptKeyRegister $desc];
    set ret [catch {uplevel 1 [list ::tcl::OptKeyParse $tempkey $arglist]} res];
    OptKeyDelete $tempkey;
    return -code $ret $res;
}

# Helper function, replacement for proc that both
# register the description under a key which is the name of the proc
# (and thus unique to that code)
# and add a first line to the code to call the OptKeyParse proc
# Stores the list of variables that have been actually given by the user
# (the other will be sets to their default value)
# into local variable named "Args".
proc ::tcl::OptProc {name desc body} {
    set namespace [uplevel 1 [list ::namespace current]];
    if {[string match "::*" $name] || [string equal $namespace "::"]} {
        # absolute name or global namespace, name is the key
        set key $name;
    } else {
        # we are relative to some non top level namespace:
        set key "${namespace}::${name}";
    }
    OptKeyRegister $desc $key;
    uplevel 1 [list ::proc $name args "set Args \[::tcl::OptKeyParse $key \$args\]\n$body"];
    return $key;
}
# Check that a argument has been given
# assumes that "OptProc" has been used as it will check in "Args" list
proc ::tcl::OptProcArgGiven {argname} {
    upvar Args alist;
    expr {[lsearch $alist $argname] >=0}
}

    #######
    # Programs/Descriptions manipulation

    # Return the instruction word/list of a given step/(sub)program
    proc OptInstr {lst} {
	lindex $lst 0;
    }
    # Is a (sub) program or a plain instruction ?
    proc OptIsPrg {lst} {
	expr {[llength [OptInstr $lst]]>=2}
    }
    # Is this instruction a program counter or a real instr
    proc OptIsCounter {item} {
	expr {[lindex $item 0]=="P"}
    }
    # Current program counter (2nd word of first word)
    proc OptGetPrgCounter {lst} {
	Lget $lst {0 1}
    }
    # Current program counter (2nd word of first word)
    proc OptSetPrgCounter {lstName newValue} {
	upvar $lstName lst;
	set lst [lreplace $lst 0 0 [concat "P" $newValue]];
    }
    # returns a list of currently selected items.
    proc OptSelection {lst} {
	set res {};
	foreach idx [lrange [lindex $lst 0] 1 end] {
	    lappend res [Lget $lst $idx];
	}
	return $res;
    }

    # Advance to next description
    proc OptNextDesc {descName} {
        uplevel 1 [list Lvarincr $descName {0 1}];
    }

    # Get the current description, eventually descend
    proc OptCurDesc {descriptions} {
        lindex $descriptions [OptGetPrgCounter $descriptions];
    }
    # get the current description, eventually descend
    # through sub programs as needed.
    proc OptCurDescFinal {descriptions} {
        set item [OptCurDesc $descriptions];
	# Descend untill we get the actual item and not a sub program
        while {[OptIsPrg $item]} {
            set item [OptCurDesc $item];
        }
	return $item;
    }
    # Current final instruction adress
    proc OptCurAddr {descriptions {start {}}} {
	set adress [OptGetPrgCounter $descriptions];
	lappend start $adress;
	set item [lindex $descriptions $adress];
	if {[OptIsPrg $item]} {
	    return [OptCurAddr $item $start];
	} else {
	    return $start;
	}
    }
    # Set the value field of the current instruction
    proc OptCurSetValue {descriptionsName value} {
	upvar $descriptionsName descriptions
	# get the current item full adress
        set adress [OptCurAddr $descriptions];
	# use the 3th field of the item  (see OptValue / OptNewInst)
	lappend adress 2
	Lvarset descriptions $adress [list 1 $value];
	#                                  ^hasBeenSet flag
    }

    # empty state means done/paste the end of the program
    proc OptState {item} {
        lindex $item 0
    }
    
    # current state
    proc OptCurState {descriptions} {
        OptState [OptCurDesc $descriptions];
    }

    #######
    # Arguments manipulation

    # Returns the argument that has to be processed now
    proc OptCurrentArg {lst} {
        lindex $lst 0;
    }
    # Advance to next argument
    proc OptNextArg {argsName} {
        uplevel 1 [list Lvarpop1 $argsName];
    }
    #######





    # Loop over all descriptions, calling OptDoOne which will
    # eventually eat all the arguments.
    proc OptDoAll {descriptionsName argumentsName} {
	upvar $descriptionsName descriptions
	upvar $argumentsName arguments;
#	puts "entered DoAll";
	# Nb: the places where "state" can be set are tricky to figure
	#     because DoOne sets the state to flagsValue and return -continue
	#     when needed...
	set state [OptCurState $descriptions];
	# We'll exit the loop in "OptDoOne" or when state is empty.
        while 1 {
	    set curitem [OptCurDesc $descriptions];
	    # Do subprograms if needed, call ourselves on the sub branch
	    while {[OptIsPrg $curitem]} {
		OptDoAll curitem arguments
#		puts "done DoAll sub";
		# Insert back the results in current tree;
		Lvarset1nc descriptions [OptGetPrgCounter $descriptions]\
			$curitem;
		OptNextDesc descriptions;
		set curitem [OptCurDesc $descriptions];
                set state [OptCurState $descriptions];
	    }
#           puts "state = \"$state\" - arguments=($arguments)";
	    if {[Lempty $state]} {
		# Nothing left to do, we are done in this branch:
		break;
	    }
	    # The following statement can make us terminate/continue
	    # as it use return -code {break, continue, return and error}
	    # codes
            OptDoOne descriptions state arguments;
	    # If we are here, no special return code where issued,
	    # we'll step to next instruction :
#           puts "new state  = \"$state\"";
	    OptNextDesc descriptions;
	    set state [OptCurState $descriptions];
        }
    }

    # Process one step for the state machine,
    # eventually consuming the current argument.
    proc OptDoOne {descriptionsName stateName argumentsName} {
        upvar $argumentsName arguments;
        upvar $descriptionsName descriptions;
	upvar $stateName state;

	# the special state/instruction "args" eats all
	# the remaining args (if any)
	if {($state == "args")} {
	    if {![Lempty $arguments]} {
		# If there is no additional arguments, leave the default value
		# in.
		OptCurSetValue descriptions $arguments;
		set arguments {};
	    }
#            puts "breaking out ('args' state: consuming every reminding args)"
	    return -code break;
	}

	if {[Lempty $arguments]} {
	    if {$state == "flags"} {
		# no argument and no flags : we're done
#                puts "returning to previous (sub)prg (no more args)";
		return -code return;
	    } elseif {$state == "optValue"} {
		set state next; # not used, for debug only
		# go to next state
		return ;
	    } else {
		return -code error [OptMissingValue $descriptions];
	    }
	} else {
	    set arg [OptCurrentArg $arguments];
	}

        switch $state {
            flags {
                # A non-dash argument terminates the options, as does --

                # Still a flag ?
                if {![OptIsFlag $arg]} {
                    # don't consume the argument, return to previous prg
                    return -code return;
                }
                # consume the flag
                OptNextArg arguments;
                if {[string equal "--" $arg]} {
                    # return from 'flags' state
                    return -code return;
                }

                set hits [OptHits descriptions $arg];
                if {$hits > 1} {
                    return -code error [OptAmbigous $descriptions $arg]
                } elseif {$hits == 0} {
                    return -code error [OptFlagUsage $descriptions $arg]
                }
		set item [OptCurDesc $descriptions];
                if {[OptNeedValue $item]} {
		    # we need a value, next state is
		    set state flagValue;
                } else {
                    OptCurSetValue descriptions 1;
                }
		# continue
		return -code continue;
            }
	    flagValue -
	    value {
		set item [OptCurDesc $descriptions];
                # Test the values against their required type
		if {[catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    return -code error [OptBadValue $item $arg $val]
		}
                # consume the value
                OptNextArg arguments;
		# set the value
		OptCurSetValue descriptions $val;
		# go to next state
		if {$state == "flagValue"} {
		    set state flags
		    return -code continue;
		} else {
		    set state next; # not used, for debug only
		    return ; # will go on next step
		}
	    }
	    optValue {
		set item [OptCurDesc $descriptions];
                # Test the values against their required type
		if {![catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    # right type, so :
		    # consume the value
		    OptNextArg arguments;
		    # set the value
		    OptCurSetValue descriptions $val;
		}
		# go to next state
		set state next; # not used, for debug only
		return ; # will go on next step
	    }
        }
	# If we reach this point: an unknown
	# state as been entered !
	return -code error "Bug! unknown state in DoOne \"$state\"\
		(prg counter [OptGetPrgCounter $descriptions]:\
			[OptCurDesc $descriptions])";
    }

# Parse the options given the key to previously registered description
# and arguments list
proc ::tcl::OptKeyParse {descKey arglist} {

    set desc [OptKeyGetDesc $descKey];

    # make sure -help always give usage
    if {[string equal -nocase "-help" $arglist]} {
	return -code error [OptError "Usage information:" $desc 1];
    }

    OptDoAll desc arglist;

    if {![Lempty $arglist]} {
	return -code error [OptTooManyArgs $desc $arglist];
    }
    
    # Analyse the result
    # Walk through the tree:
    OptTreeVars $desc "#[expr {[info level]-1}]" ;
}

    # determine string length for nice tabulated output
    proc OptTreeVars {desc level {vnamesLst {}}} {
	foreach item $desc {
	    if {[OptIsCounter $item]} continue;
	    if {[OptIsPrg $item]} {
		set vnamesLst [OptTreeVars $item $level $vnamesLst];
	    } else {
		set vname [OptVarName $item];
		upvar $level $vname var
		if {[OptHasBeenSet $item]} {
#		    puts "adding $vname"
		    # lets use the input name for the returned list
		    # it is more usefull, for instance you can check that
		    # no flags at all was given with expr
		    # {![string match "*-*" $Args]}
		    lappend vnamesLst [OptName $item];
		    set var [OptValue $item];
		} else {
		    set var [OptDefaultValue $item];
		}
	    }
	}
	return $vnamesLst
    }


# Check the type of a value
# and emit an error if arg is not of the correct type
# otherwise returns the canonical value of that arg (ie 0/1 for booleans)
proc ::tcl::OptCheckType {arg type {typeArgs ""}} {
#    puts "checking '$arg' against '$type' ($typeArgs)";

    # only types "any", "choice", and numbers can have leading "-"

    switch -exact -- $type {
        int {
            if {![string is integer -strict $arg]} {
                error "not an integer"
            }
	    return $arg;
        }
        float {
            return [expr {double($arg)}]
        }
	script -
        list {
	    # if llength fail : malformed list
            if {[llength $arg]==0 && [OptIsFlag $arg]} {
		error "no values with leading -"
	    }
	    return $arg;
        }
        boolean {
	    if {![string is boolean -strict $arg]} {
		error "non canonic boolean"
            }
	    # convert true/false because expr/if is broken with "!,...
	    return [expr {$arg ? 1 : 0}]
        }
        choice {
            if {[lsearch -exact $typeArgs $arg] < 0} {
                error "invalid choice"
            }
	    return $arg;
        }
	any {
	    return $arg;
	}
	string -
	default {
            if {[OptIsFlag $arg]} {
                error "no values with leading -"
            }
	    return $arg
        }
    }
    return neverReached;
}

    # internal utilities

    # returns the number of flags matching the given arg
    # sets the (local) prg counter to the list of matches
    proc OptHits {descName arg} {
        upvar $descName desc;
        set hits 0
        set hitems {}
	set i 1;

	set larg [string tolower $arg];
	set len  [string length $larg];
	set last [expr {$len-1}];

        foreach item [lrange $desc 1 end] {
            set flag [OptName $item]
	    # lets try to match case insensitively
	    # (string length ought to be cheap)
	    set lflag [string tolower $flag];
	    if {$len == [string length $lflag]} {
		if {[string equal $larg $lflag]} {
		    # Exact match case
		    OptSetPrgCounter desc $i;
		    return 1;
		}
	    } elseif {[string equal $larg [string range $lflag 0 $last]]} {
		lappend hitems $i;
		incr hits;
            }
	    incr i;
        }
	if {$hits} {
	    OptSetPrgCounter desc $hitems;
	}
        return $hits
    }

    # Extract fields from the list structure:

    proc OptName {item} {
        lindex $item 1;
    }
    proc OptHasBeenSet {item} {
	Lget $item {2 0};
    }
    proc OptValue {item} {
	Lget $item {2 1};
    }

    proc OptIsFlag {name} {
        string match "-*" $name;
    }
    proc OptIsOpt {name} {
        string match {\?*} $name;
    }
    proc OptVarName {item} {
        set name [OptName $item];
        if {[OptIsFlag $name]} {
            return [string range $name 1 end];
        } elseif {[OptIsOpt $name]} {
	    return [string trim $name "?"];
	} else {
            return $name;
        }
    }
    proc OptType {item} {
        lindex $item 3
    }
    proc OptTypeArgs {item} {
        lindex $item 4
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
        return $val
    }

    # Description format error helper
    proc OptOptUsage {item {what ""}} {
        return -code error "invalid description format$what: $item\n\
                should be a list of {varname|-flagname ?-type? ?defaultvalue?\
                ?helpstring?}"
    }


    # Generate a canonical form single instruction
    proc OptNewInst {state varname type typeArgs help} {
	list $state $varname [list 0 {}] $type $typeArgs $help
	#                          ^  ^
	#                          |  |
	#               hasBeenSet=+  +=currentValue
    }

    # Translate one item to canonical form
    proc OptNormalizeOne {item} {
        set lg [Lassign $item varname arg1 arg2 arg3]
#       puts "called optnormalizeone '$item' v=($varname), lg=$lg"
        set isflag [OptIsFlag $varname]
	set isopt  [OptIsOpt  $varname]
        if {$isflag} {
            set state "flags"
        } elseif {$isopt} {
	    set state "optValue"
	} elseif {![string equal $varname "args"]} {
	    set state "value"
	} else {
	    set state "args"
	}

	# apply 'smart' 'fuzzy' logic to try to make
	# description writer's life easy, and our's difficult :
	# let's guess the missing arguments :-)

        switch $lg {
            1 {
                if {$isflag} {
                    return [OptNewInst $state $varname boolflag false ""]
                } else {
                    return [OptNewInst $state $varname any "" ""]
                }
            }
            2 {
                # varname default
                # varname help
                set type [OptGuessType $arg1]
                if {[string equal $type "string"]} {
                    if {$isflag} {
			set type boolflag
			set def false
		    } else {
			set type any
			set def ""
		    }
		    set help $arg1
                } else {
                    set help ""
                    set def $arg1
                }
                return [OptNewInst $state $varname $type $def $help]
            }
            3 {
                # varname type value
                # varname value comment

                if {[regexp {^-(.+)$} $arg1 x type]} {
		    # flags/optValue as they are optional, need a "value",
		    # on the contrary, for a variable (non optional),
	            # default value is pointless, 'cept for choices :
		    if {$isflag || $isopt || ($type == "choice")} {
			return [OptNewInst $state $varname $type $arg2 ""]
		    } else {
			return [OptNewInst $state $varname $type "" $arg2]
		    }
                } else {
                    return [OptNewInst $state $varname\
			    [OptGuessType $arg1] $arg1 $arg2]
                }
            }
            4 {
                if {[regexp {^-(.+)$} $arg1 x type]} {
		    return [OptNewInst $state $varname $type $arg2 $arg3]
                } else {
                    return -code error [OptOptUsage $item]
                }
            }
            default {
                return -code error [OptOptUsage $item]
            }
        }
    }

    # Auto magic lazy type determination
    proc OptGuessType {arg} {
 	 if { $arg == "true" || $arg == "false" } {







|





|







|
|
|
|

|

|

|

|









|

|



















|




|





|

|








|

|



|







715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
        return $val
    }

    # Description format error helper
    proc OptOptUsage {item {what ""}} {
        return -code error "invalid description format$what: $item\n\
                should be a list of {varname|-flagname ?-type? ?defaultvalue?\
                ?helpstring?}";
    }


    # Generate a canonical form single instruction
    proc OptNewInst {state varname type typeArgs help} {
	list $state $varname [list 0 {}] $type $typeArgs $help;
	#                          ^  ^
	#                          |  |
	#               hasBeenSet=+  +=currentValue
    }

    # Translate one item to canonical form
    proc OptNormalizeOne {item} {
        set lg [Lassign $item varname arg1 arg2 arg3];
#       puts "called optnormalizeone '$item' v=($varname), lg=$lg";
        set isflag [OptIsFlag $varname];
	set isopt  [OptIsOpt  $varname];
        if {$isflag} {
            set state "flags";
        } elseif {$isopt} {
	    set state "optValue";
	} elseif {![string equal $varname "args"]} {
	    set state "value";
	} else {
	    set state "args";
	}

	# apply 'smart' 'fuzzy' logic to try to make
	# description writer's life easy, and our's difficult :
	# let's guess the missing arguments :-)

        switch $lg {
            1 {
                if {$isflag} {
                    return [OptNewInst $state $varname boolflag false ""];
                } else {
                    return [OptNewInst $state $varname any "" ""];
                }
            }
            2 {
                # varname default
                # varname help
                set type [OptGuessType $arg1]
                if {[string equal $type "string"]} {
                    if {$isflag} {
			set type boolflag
			set def false
		    } else {
			set type any
			set def ""
		    }
		    set help $arg1
                } else {
                    set help ""
                    set def $arg1
                }
                return [OptNewInst $state $varname $type $def $help];
            }
            3 {
                # varname type value
                # varname value comment
		
                if {[regexp {^-(.+)$} $arg1 x type]} {
		    # flags/optValue as they are optional, need a "value",
		    # on the contrary, for a variable (non optional),
	            # default value is pointless, 'cept for choices :
		    if {$isflag || $isopt || ($type == "choice")} {
			return [OptNewInst $state $varname $type $arg2 ""];
		    } else {
			return [OptNewInst $state $varname $type "" $arg2];
		    }
                } else {
                    return [OptNewInst $state $varname\
			    [OptGuessType $arg1] $arg1 $arg2]
                }
            }
            4 {
                if {[regexp {^-(.+)$} $arg1 x type]} {
		    return [OptNewInst $state $varname $type $arg2 $arg3];
                } else {
                    return -code error [OptOptUsage $item];
                }
            }
            default {
                return -code error [OptOptUsage $item];
            }
        }
    }

    # Auto magic lazy type determination
    proc OptGuessType {arg} {
 	 if { $arg == "true" || $arg == "false" } {
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

    # Error messages front ends

    proc OptAmbigous {desc arg} {
        OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc]
    }
    proc OptFlagUsage {desc arg} {
        OptError "bad flag \"$arg\", must be one of" $desc
    }
    proc OptTooManyArgs {desc arguments} {
        OptError "too many arguments (unexpected argument(s): $arguments),\
		usage:"\
		$desc 1
    }
    proc OptParamType {item} {
	if {[OptIsFlag $item]} {
	    return "flag"
	} else {
	    return "parameter"
	}
    }
    proc OptBadValue {item arg {err {}}} {
#       puts "bad val err = \"$err\""
        OptError "bad value \"$arg\" for [OptParamType $item]"\
		[list $item]
    }
    proc OptMissingValue {descriptions} {
#        set item [OptCurDescFinal $descriptions]
        set item [OptCurDesc $descriptions]
        OptError "no value given for [OptParamType $item] \"[OptName $item]\"\
		(use -help for full usage) :"\
		[list $item]
    }

proc ::tcl::OptKeyError {prefix descKey {header 0}} {
    OptError $prefix [OptKeyGetDesc $descKey] $header
}

    # determine string length for nice tabulated output
    proc OptLengths {desc nlName tlName dlName} {
	upvar $nlName nl
	upvar $tlName tl
	upvar $dlName dl
	foreach item $desc {
	    if {[OptIsCounter $item]} continue
	    if {[OptIsPrg $item]} {
		OptLengths $item nl tl dl
	    } else {
		SetMax nl [string length [OptName $item]]
		SetMax tl [string length [OptType $item]]
		set dv [OptTypeArgs $item]
		if {[OptState $item] != "header"} {
		    set dv "($dv)"
		}
		set l [string length $dv]
		# limit the space allocated to potentially big "choices"
		if {([OptType $item] != "choice") || ($l<=12)} {
		    SetMax dl $l
		} else {
		    if {![info exists dl]} {
			set dl 0
		    }
		}
	    }
	}
    }
    # output the tree
    proc OptTree {desc nl tl dl} {
	set res ""
	foreach item $desc {
	    if {[OptIsCounter $item]} continue
	    if {[OptIsPrg $item]} {
		append res [OptTree $item $nl $tl $dl]
	    } else {
		set dv [OptTypeArgs $item]
		if {[OptState $item] != "header"} {
		    set dv "($dv)"
		}
		append res [string trimright [format "\n    %-*s %-*s %-*s %s" \
			$nl [OptName $item] $tl [OptType $item] \
			$dl $dv [OptHelp $item]]]
	    }
	}
	return $res
    }

# Give nice usage string
proc ::tcl::OptError {prefix desc {header 0}} {
    # determine length
    if {$header} {
	# add faked instruction
	set h [list [OptNewInst header Var/FlagName Type Value Help]]
	lappend h   [OptNewInst header ------------ ---- ----- ----]
	lappend h   [OptNewInst header {(-help} "" "" {gives this help)}]
	set desc [concat $h $desc]
    }
    OptLengths $desc nl tl dl
    # actually output
    return "$prefix[OptTree $desc $nl $tl $dl]"
}


################     General Utility functions   #######################

#







|








|

|



|




|
|






|




|
|
|

|





|

|

|













|

|

|

|

|

|

|


|







|
|
|



|







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

    # Error messages front ends

    proc OptAmbigous {desc arg} {
        OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc]
    }
    proc OptFlagUsage {desc arg} {
        OptError "bad flag \"$arg\", must be one of" $desc;
    }
    proc OptTooManyArgs {desc arguments} {
        OptError "too many arguments (unexpected argument(s): $arguments),\
		usage:"\
		$desc 1
    }
    proc OptParamType {item} {
	if {[OptIsFlag $item]} {
	    return "flag";
	} else {
	    return "parameter";
	}
    }
    proc OptBadValue {item arg {err {}}} {
#       puts "bad val err = \"$err\"";
        OptError "bad value \"$arg\" for [OptParamType $item]"\
		[list $item]
    }
    proc OptMissingValue {descriptions} {
#        set item [OptCurDescFinal $descriptions];
        set item [OptCurDesc $descriptions];
        OptError "no value given for [OptParamType $item] \"[OptName $item]\"\
		(use -help for full usage) :"\
		[list $item]
    }

proc ::tcl::OptKeyError {prefix descKey {header 0}} {
    OptError $prefix [OptKeyGetDesc $descKey] $header;
}

    # determine string length for nice tabulated output
    proc OptLengths {desc nlName tlName dlName} {
	upvar $nlName nl;
	upvar $tlName tl;
	upvar $dlName dl;
	foreach item $desc {
	    if {[OptIsCounter $item]} continue;
	    if {[OptIsPrg $item]} {
		OptLengths $item nl tl dl
	    } else {
		SetMax nl [string length [OptName $item]]
		SetMax tl [string length [OptType $item]]
		set dv [OptTypeArgs $item];
		if {[OptState $item] != "header"} {
		    set dv "($dv)";
		}
		set l [string length $dv];
		# limit the space allocated to potentially big "choices"
		if {([OptType $item] != "choice") || ($l<=12)} {
		    SetMax dl $l
		} else {
		    if {![info exists dl]} {
			set dl 0
		    }
		}
	    }
	}
    }
    # output the tree
    proc OptTree {desc nl tl dl} {
	set res "";
	foreach item $desc {
	    if {[OptIsCounter $item]} continue;
	    if {[OptIsPrg $item]} {
		append res [OptTree $item $nl $tl $dl];
	    } else {
		set dv [OptTypeArgs $item];
		if {[OptState $item] != "header"} {
		    set dv "($dv)";
		}
		append res [format "\n    %-*s %-*s %-*s %s" \
			$nl [OptName $item] $tl [OptType $item] \
			$dl $dv [OptHelp $item]]
	    }
	}
	return $res;
    }

# Give nice usage string
proc ::tcl::OptError {prefix desc {header 0}} {
    # determine length
    if {$header} {
	# add faked instruction
	set h [list [OptNewInst header Var/FlagName Type Value Help]];
	lappend h   [OptNewInst header ------------ ---- ----- ----];
	lappend h   [OptNewInst header {( -help} "" "" {gives this help )}]
	set desc [concat $h $desc]
    }
    OptLengths $desc nl tl dl
    # actually output 
    return "$prefix[OptTree $desc $nl $tl $dl]"
}


################     General Utility functions   #######################

#
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
proc ::tcl::Lempty {list} {
    expr {[llength $list]==0}
}

# Gets the value of one leaf of a lists tree
proc ::tcl::Lget {list indexLst} {
    if {[llength $indexLst] <= 1} {
        return [lindex $list $indexLst]
    }
    Lget [lindex $list [lindex $indexLst 0]] [lrange $indexLst 1 end]
}
# Sets the value of one leaf of a lists tree
# (we use the version that does not create the elements because
#  it would be even slower... needs to be written in C !)
# (nb: there is a non trivial recursive problem with indexes 0,
#  which appear because there is no difference between a list
#  of 1 element and 1 element alone : [list "a"] == "a" while
#  it should be {a} and [listp a] should be 0 while [listp {a b}] would be 1
#  and [listp "a b"] maybe 0. listp does not exist either...)
proc ::tcl::Lvarset {listName indexLst newValue} {
    upvar $listName list
    if {[llength $indexLst] <= 1} {
        Lvarset1nc list $indexLst $newValue
    } else {
        set idx [lindex $indexLst 0]
        set targetList [lindex $list $idx]
        # reduce refcount on targetList (not really usefull now,
	# could be with optimizing compiler)
#        Lvarset1 list $idx {}
        # recursively replace in targetList
        Lvarset targetList [lrange $indexLst 1 end] $newValue
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList
    }
}
# Set one cell to a value, eventually create all the needed elements
# (on level-1 of lists)
variable emptyList {}
proc ::tcl::Lvarset1 {listName index newValue} {
    upvar $listName list
    if {$index < 0} {return -code error "invalid negative index"}
    set lg [llength $list]
    if {$index >= $lg} {
        variable emptyList
        for {set i $lg} {$i<$index} {incr i} {
            lappend list $emptyList
        }
        lappend list $newValue
    } else {
        set list [lreplace $list $index $index $newValue]
    }
}
# same as Lvarset1 but no bound checking / creation
proc ::tcl::Lvarset1nc {listName index newValue} {
    upvar $listName list
    set list [lreplace $list $index $index $newValue]
}
# Increments the value of one leaf of a lists tree
# (which must exists)
proc ::tcl::Lvarincr {listName indexLst {howMuch 1}} {
    upvar $listName list
    if {[llength $indexLst] <= 1} {
        Lvarincr1 list $indexLst $howMuch
    } else {
        set idx [lindex $indexLst 0]
        set targetList [lindex $list $idx]
        # reduce refcount on targetList
        Lvarset1nc list $idx {}
        # recursively replace in targetList
        Lvarincr targetList [lrange $indexLst 1 end] $howMuch
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList
    }
}
# Increments the value of one cell of a list
proc ::tcl::Lvarincr1 {listName index {howMuch 1}} {
    upvar $listName list
    set newValue [expr {[lindex $list $index]+$howMuch}]
    set list [lreplace $list $index $index $newValue]
    return $newValue
}
# Removes the first element of a list
# and returns the new list value
proc ::tcl::Lvarpop1 {listName} {
    upvar $listName list
    set list [lrange $list 1 end]
}
# Same but returns the removed element
# (Like the tclX version)
proc ::tcl::Lvarpop {listName} {
    upvar $listName list
    set el [lindex $list 0]
    set list [lrange $list 1 end]
    return $el
}
# Assign list elements to variables and return the length of the list
proc ::tcl::Lassign {list args} {
    # faster than direct blown foreach (which does not byte compile)
    set i 0
    set lg [llength $list]
    foreach vname $args {
        if {$i>=$lg} break
        uplevel 1 [list ::set $vname [lindex $list $i]]
        incr i
    }
    return $lg
}

# Misc utilities

# Set the varname to value if value is greater than varname's current value
# or if varname is undefined
proc ::tcl::SetMax {varname value} {







|

|






|



|

|

|
|


|

|

|






|

|

|

|

|

|




|
|




|

|

|
|

|

|

|




|
|
|
|




|
|




|
|
|
|




|
|


|
|

|







939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
proc ::tcl::Lempty {list} {
    expr {[llength $list]==0}
}

# Gets the value of one leaf of a lists tree
proc ::tcl::Lget {list indexLst} {
    if {[llength $indexLst] <= 1} {
        return [lindex $list $indexLst];
    }
    Lget [lindex $list [lindex $indexLst 0]] [lrange $indexLst 1 end];
}
# Sets the value of one leaf of a lists tree
# (we use the version that does not create the elements because
#  it would be even slower... needs to be written in C !)
# (nb: there is a non trivial recursive problem with indexes 0,
#  which appear because there is no difference between a list
#  of 1 element and 1 element alone : [list "a"] == "a" while 
#  it should be {a} and [listp a] should be 0 while [listp {a b}] would be 1
#  and [listp "a b"] maybe 0. listp does not exist either...)
proc ::tcl::Lvarset {listName indexLst newValue} {
    upvar $listName list;
    if {[llength $indexLst] <= 1} {
        Lvarset1nc list $indexLst $newValue;
    } else {
        set idx [lindex $indexLst 0];
        set targetList [lindex $list $idx];
        # reduce refcount on targetList (not really usefull now,
	# could be with optimizing compiler)
#        Lvarset1 list $idx {};
        # recursively replace in targetList
        Lvarset targetList [lrange $indexLst 1 end] $newValue;
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList;
    }
}
# Set one cell to a value, eventually create all the needed elements
# (on level-1 of lists)
variable emptyList {}
proc ::tcl::Lvarset1 {listName index newValue} {
    upvar $listName list;
    if {$index < 0} {return -code error "invalid negative index"}
    set lg [llength $list];
    if {$index >= $lg} {
        variable emptyList;
        for {set i $lg} {$i<$index} {incr i} {
            lappend list $emptyList;
        }
        lappend list $newValue;
    } else {
        set list [lreplace $list $index $index $newValue];
    }
}
# same as Lvarset1 but no bound checking / creation
proc ::tcl::Lvarset1nc {listName index newValue} {
    upvar $listName list;
    set list [lreplace $list $index $index $newValue];
}
# Increments the value of one leaf of a lists tree
# (which must exists)
proc ::tcl::Lvarincr {listName indexLst {howMuch 1}} {
    upvar $listName list;
    if {[llength $indexLst] <= 1} {
        Lvarincr1 list $indexLst $howMuch;
    } else {
        set idx [lindex $indexLst 0];
        set targetList [lindex $list $idx];
        # reduce refcount on targetList
        Lvarset1nc list $idx {};
        # recursively replace in targetList
        Lvarincr targetList [lrange $indexLst 1 end] $howMuch;
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList;
    }
}
# Increments the value of one cell of a list
proc ::tcl::Lvarincr1 {listName index {howMuch 1}} {
    upvar $listName list;
    set newValue [expr {[lindex $list $index]+$howMuch}];
    set list [lreplace $list $index $index $newValue];
    return $newValue;
}
# Removes the first element of a list
# and returns the new list value
proc ::tcl::Lvarpop1 {listName} {
    upvar $listName list;
    set list [lrange $list 1 end];
}
# Same but returns the removed element
# (Like the tclX version)
proc ::tcl::Lvarpop {listName} {
    upvar $listName list;
    set el [lindex $list 0];
    set list [lrange $list 1 end];
    return $el;
}
# Assign list elements to variables and return the length of the list
proc ::tcl::Lassign {list args} {
    # faster than direct blown foreach (which does not byte compile)
    set i 0;
    set lg [llength $list];
    foreach vname $args {
        if {$i>=$lg} break
        uplevel 1 [list ::set $vname [lindex $list $i]];
        incr i;
    }
    return $lg;
}

# Misc utilities

# Set the varname to value if value is greater than varname's current value
# or if varname is undefined
proc ::tcl::SetMax {varname value} {

Changes to library/opt/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded opt 0.4.7 [list source [file join $dir optparse.tcl]]










|
|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded opt 0.4.5 [list source [file join $dir optparse.tcl]]

Changes to library/platform/pkgIndex.tcl.

1
2
3
package ifneeded platform        1.0.18 [list source [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source [file join $dir shell.tcl]]

|


1
2
3
package ifneeded platform        1.0.14 [list source [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source [file join $dir shell.tcl]]

Changes to library/platform/platform.tcl.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# result.
#
# General
# Only the first element of 'os' is used - we don't care whether we
# are on "Windows NT" or "Windows XP" or whatever.
#
# Machine specific
# % amd64  -> x86_64
# % arm*   -> arm
# % sun4*  -> sparc
# % ia32*  -> ix86
# % intel  -> ix86
# % i*86*  -> ix86
# % Power* -> powerpc
# % x86_64 + wordSize 4 => x86 code
#
# OS specific
# % AIX are always powerpc machines







<


<







25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
# result.
#
# General
# Only the first element of 'os' is used - we don't care whether we
# are on "Windows NT" or "Windows XP" or whatever.
#
# Machine specific

# % arm*   -> arm
# % sun4*  -> sparc

# % intel  -> ix86
# % i*86*  -> ix86
# % Power* -> powerpc
# % x86_64 + wordSize 4 => x86 code
#
# OS specific
# % AIX are always powerpc machines
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
    set cpu  $tcl_platform(machine)

    switch -glob -- $cpu {
	sun4* {
	    set cpu sparc
	}
	intel -
	ia32* -
	i*86* {
	    set cpu ix86
	}
	x86_64 {
	    if {$tcl_platform(wordSize) == 4} {
		# See Example <1> at the top of this file.
		set cpu ix86
	    }
	}
	ppc -
	"Power*" {
	    set cpu powerpc
	}
	"arm*" {
	    set cpu arm
	}
	ia64 {
	    if {$tcl_platform(wordSize) == 4} {
		append cpu _32
	    }
	}
    }

    switch -glob -- $plat {



	windows {
	    if {$tcl_platform(platform) == "unix"} {
		set plat cygwin
	    } else {
		set plat win32
	    }
	    if {$cpu eq "amd64"} {







<









<














>
>
>







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
    set cpu  $tcl_platform(machine)

    switch -glob -- $cpu {
	sun4* {
	    set cpu sparc
	}
	intel -

	i*86* {
	    set cpu ix86
	}
	x86_64 {
	    if {$tcl_platform(wordSize) == 4} {
		# See Example <1> at the top of this file.
		set cpu ix86
	    }
	}

	"Power*" {
	    set cpu powerpc
	}
	"arm*" {
	    set cpu arm
	}
	ia64 {
	    if {$tcl_platform(wordSize) == 4} {
		append cpu _32
	    }
	}
    }

    switch -glob -- $plat {
	cygwin* {
	    set plat cygwin
	}
	windows {
	    if {$tcl_platform(platform) == "unix"} {
		set plat cygwin
	    } else {
		set plat win32
	    }
	    if {$cpu eq "amd64"} {
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
		    append cpu 64
		}
	    }
	}
	osf1 {
	    set plat tru64
	}
	default {
	    set plat [lindex [split $plat _-] 0]
	}
    }

    return "${plat}-${cpu}"
}

# -- platform::identify
#







<
<
<







145
146
147
148
149
150
151



152
153
154
155
156
157
158
		    append cpu 64
		}
	    }
	}
	osf1 {
	    set plat tru64
	}



    }

    return "${plat}-${cpu}"
}

# -- platform::identify
#
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	solaris {
	    regsub {^5} $tcl_platform(osVersion) 2 text
	    append plat $text
	    return "${plat}-${cpu}"
	}
	macosx {
	    set major [lindex [split $tcl_platform(osVersion) .] 0]
	    if {$major > 19} {
		set minor [lindex [split $tcl_platform(osVersion) .] 1]
		incr major -9
		append plat $major.[expr {$minor - 1}]
	    } else {
		incr major -4
		append plat 10.$major
		return "${plat}-${cpu}"
	    }
	    return "${plat}-${cpu}"
	}
	linux {
	    # Look for the libc*.so and determine its version
	    # (libc5/6, libc6 further glibc 2.X)

	    set v unknown








|
<
<
<
<




<







171
172
173
174
175
176
177
178




179
180
181
182

183
184
185
186
187
188
189
	solaris {
	    regsub {^5} $tcl_platform(osVersion) 2 text
	    append plat $text
	    return "${plat}-${cpu}"
	}
	macosx {
	    set major [lindex [split $tcl_platform(osVersion) .] 0]
	    if {$major > 8} {




		incr major -4
		append plat 10.$major
		return "${plat}-${cpu}"
	    }

	}
	linux {
	    # Look for the libc*.so and determine its version
	    # (libc5/6, libc6 further glibc 2.X)

	    set v unknown

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macosx*-*    {
	    # 10.5+,11.0+
	    if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} {

		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  {
			if {[lindex [split $::tcl_platform(osVersion) .] 0] < 19} {
			    set alt i386-x86_64
			} else {
			    set alt {}
			}
		    }
		    arm  {
			lappend alt x86_64
		    }
		    default { set alt {} }
		}

		if {$v ne ""} {
		    foreach {major minor} [split $v .] break

		    set res {}
		    if {$major eq 12} {
			# Add 12.0 to 12.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 11
			set minor 5
		    }
		    if {$major eq 11} {
			# Add 11.0 to 11.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 10
			set minor 15
		    }
		    # Add 10.5 to 10.minor to patterns.

		    for {set j $minor} {$j >= 5} {incr j -1} {
			if {$cpu ne "arm"} {
			    lappend res macosx${major}.${j}-${cpu}
			}
			foreach a $alt {
			    lappend res macosx${major}.${j}-$a
			}
		    }

		    # Add unversioned patterns for 10.3/10.4 builds.
		    lappend res macosx-${cpu}







|







|
<
<
<
<
<
<
<
<
<






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>

<
|
<







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341









342
343
344
345
346
347























348
349
350

351

352
353
354
355
356
357
358
	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macosx*-*    {
	    # 10.5+
	    if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} {

		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  { lappend alt i386-x86_64 }









		    default { set alt {} }
		}

		if {$v ne ""} {
		    foreach {major minor} [split $v .] break
























		    # Add 10.5 to 10.minor to patterns.
		    set res {}
		    for {set j $minor} {$j >= 5} {incr j -1} {

			lappend res macosx${major}.${j}-${cpu}

			foreach a $alt {
			    lappend res macosx${major}.${j}-$a
			}
		    }

		    # Add unversioned patterns for 10.3/10.4 builds.
		    lappend res macosx-${cpu}
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
    return $res
}


# ### ### ### ######### ######### #########
## Ready

package provide platform 1.0.18

# ### ### ### ######### ######### #########
## Demo application

if {[info exists argv0] && ($argv0 eq [info script])} {
    puts ====================================
    parray tcl_platform







|







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    return $res
}


# ### ### ### ######### ######### #########
## Ready

package provide platform 1.0.14

# ### ### ### ######### ######### #########
## Demo application

if {[info exists argv0] && ($argv0 eq [info script])} {
    puts ====================================
    parray tcl_platform

Changes to library/reg/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
if {![package vsatisfies [package provide Tcl] 8.5]} return
if {[info sharedlibextension] != ".dll"} return
if {[::tcl::pkgconfig get debug]} {
    package ifneeded registry 1.3.5 \
            [list load [file join $dir tclreg13g.dll] Registry]
} else {
    package ifneeded registry 1.3.5 \
            [list load [file join $dir tclreg13.dll] Registry]
}
|

|
|
|

|
|

1
2
3
4
5
6
7
8
9
if {![package vsatisfies [package provide Tcl] 8]} return
if {[info sharedlibextension] != ".dll"} return
if {[info exists ::tcl_platform(debug)]} {
    package ifneeded registry 1.2.2 \
            [list load [file join $dir tclreg12g.dll] registry]
} else {
    package ifneeded registry 1.2.2 \
            [list load [file join $dir tclreg12.dll] registry]
}

Changes to library/safe.tcl.

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	    CheckInterp $slave
	    namespace upvar ::safe S$slave state

	    return [join [list \
		[list -accessPath $state(access_path)] \
		[list -statics    $state(staticsok)]   \
		[list -nested     $state(nestedok)]    \
		[list -deleteHook $state(cleanupHook)]]]
	}
	2 {
	    # If we have exactly 2 arguments the semantic is a "configure
	    # get"
	    lassign $args slave arg

	    # get the flag sub program (we 'know' about Opt's internal







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	    CheckInterp $slave
	    namespace upvar ::safe S$slave state

	    return [join [list \
		[list -accessPath $state(access_path)] \
		[list -statics    $state(staticsok)]   \
		[list -nested     $state(nestedok)]    \
	        [list -deleteHook $state(cleanupHook)]]]
	}
	2 {
	    # If we have exactly 2 arguments the semantic is a "configure
	    # get"
	    lassign $args slave arg

	    # get the flag sub program (we 'know' about Opt's internal
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864

    # Passed all the tests, lets source it. Note that we do this all manually
    # because we want to control [info script] in the slave so information
    # doesn't leak so much. [Bug 2913625]
    set old [::interp eval $slave {info script}]
    set code [catch {
	set f [open $realfile]
	fconfigure $f -eofchar "\032 {}"
	if {$encoding ne ""} {
	    fconfigure $f -encoding $encoding
	}
	set contents [read $f]
	close $f
	::interp eval $slave [list info script $file]
	::interp eval $slave $contents







|







850
851
852
853
854
855
856
857
858
859
860
861
862
863
864

    # Passed all the tests, lets source it. Note that we do this all manually
    # because we want to control [info script] in the slave so information
    # doesn't leak so much. [Bug 2913625]
    set old [::interp eval $slave {info script}]
    set code [catch {
	set f [open $realfile]
	fconfigure $f -eofchar \032
	if {$encoding ne ""} {
	    fconfigure $f -encoding $encoding
	}
	set contents [read $f]
	close $f
	::interp eval $slave [list info script $file]
	::interp eval $slave $contents

Changes to library/tclIndex.

81
82
83
84
85
86
87
88
89
90
set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]]
set auto_index(::tcl::tm::add) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::remove) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::list) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::UnknownHandler) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::roots) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::path) [list source [file join $dir tm.tcl]]
if {[namespace exists ::tcl::unsupported]} {
    set auto_index(timerate) {namespace import ::tcl::unsupported::timerate}
}







<
<
<
81
82
83
84
85
86
87



set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]]
set auto_index(::tcl::tm::add) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::remove) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::list) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::UnknownHandler) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::roots) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::path) [list source [file join $dir tm.tcl]]



Changes to library/tcltest/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.3 [list source [file join $dir tcltest.tcl]]










|
|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded tcltest 2.3.8 [list source [file join $dir tcltest.tcl]]

Changes to library/tcltest/tcltest.tcl.

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
# tcltest.tcl --
#
#	This file contains support code for the Tcl test suite.  It
#       defines the tcltest namespace and finds and defines the output
#       directory, constraints available, output and error channels,
#	etc. used by Tcl tests.  See the tcltest man page for more
#	details.
#
#       This design was based on the Tcl testing approach designed and
#       initially implemented by Mary Ann May-Pumphrey of Sun
#	Microsystems.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2000 Ajuba Solutions
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
# All rights reserved.

package require Tcl 8.5-		;# -verbose line uses [info frame]
namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.5.3

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package provide Tcl] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package provide Tcl]
    variable patchLevel [info patchlevel]

##### Export the public tcltest procs; several categories
    #
    # Export the main functional commands that do useful things
    namespace export cleanupTests loadTestedCommands makeDirectory \
	makeFile removeDirectory removeFile runAllTests test

    # Export configuration commands that control the functional commands
    namespace export configure customMatch errorChannel interpreter \
	    outputChannel testConstraint

    # Export commands that are duplication (candidates for deprecation)
    if {![package vsatisfies [package provide Tcl] 8.7-]} {
	namespace export bytestring	;# dups [encoding convertfrom identity]
    }
    namespace export debug		;#	[configure -debug]
    namespace export errorFile		;#	[configure -errfile]
    namespace export limitConstraints	;#	[configure -limitconstraints]
    namespace export loadFile		;#	[configure -loadfile]
    namespace export loadScript		;#	[configure -load]
    namespace export match		;#	[configure -match]
    namespace export matchFiles		;#	[configure -file]













|
|



|





|


















<
|
<







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
# tcltest.tcl --
#
#	This file contains support code for the Tcl test suite.  It
#       defines the tcltest namespace and finds and defines the output
#       directory, constraints available, output and error channels,
#	etc. used by Tcl tests.  See the tcltest man page for more
#	details.
#
#       This design was based on the Tcl testing approach designed and
#       initially implemented by Mary Ann May-Pumphrey of Sun
#	Microsystems.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
# All rights reserved.

package require Tcl 8.5		;# -verbose line uses [info frame]
namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.3.8

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package provide Tcl] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package provide Tcl]
    variable patchLevel [info patchlevel]

##### Export the public tcltest procs; several categories
    #
    # Export the main functional commands that do useful things
    namespace export cleanupTests loadTestedCommands makeDirectory \
	makeFile removeDirectory removeFile runAllTests test

    # Export configuration commands that control the functional commands
    namespace export configure customMatch errorChannel interpreter \
	    outputChannel testConstraint

    # Export commands that are duplication (candidates for deprecation)

    namespace export bytestring		;# dups [encoding convertfrom identity]

    namespace export debug		;#	[configure -debug]
    namespace export errorFile		;#	[configure -errfile]
    namespace export limitConstraints	;#	[configure -limitconstraints]
    namespace export loadFile		;#	[configure -loadfile]
    namespace export loadScript		;#	[configure -load]
    namespace export match		;#	[configure -match]
    namespace export matchFiles		;#	[configure -file]
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
    proc outputChannel { {filename ""} } {
	variable outputChannel
	variable ChannelsWeOpened

	# This is very subtle and tricky, so let me try to explain.
	# (Hopefully this longer comment will be clear when I come
	# back in a few months, unlike its predecessor :) )
	#
	# The [outputChannel] command (and underlying variable) have to
	# be kept in sync with the [configure -outfile] configuration
	# option ( and underlying variable Option(-outfile) ).  This is
	# accomplished with a write trace on Option(-outfile) that will
	# update [outputChannel] whenver a new value is written.  That
	# much is easy.
	#
	# The trick is that in order to maintain compatibility with
	# version 1 of tcltest, we must allow every configuration option
	# to get its inital value from command line arguments.  This is
	# accomplished by setting initial read traces on all the
	# configuration options to parse the command line option the first
	# time they are read.  These traces are cancelled whenever the
	# program itself calls [configure].
	#
	# OK, then so to support tcltest 1 compatibility, it seems we want
	# to get the return from [outputFile] to trigger the read traces,
	# just in case.
	#
	# BUT!  A little known feature of Tcl variable traces is that
	# traces are disabled during the handling of other traces.  So,
	# if we trigger read traces on Option(-outfile) and that triggers
	# command line parsing which turns around and sets an initial
	# value for Option(-outfile) -- <whew!> -- the write trace that
	# would keep [outputChannel] in sync with that new initial value
	# would not fire!
	#







|














|




|







343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
    proc outputChannel { {filename ""} } {
	variable outputChannel
	variable ChannelsWeOpened

	# This is very subtle and tricky, so let me try to explain.
	# (Hopefully this longer comment will be clear when I come
	# back in a few months, unlike its predecessor :) )
	# 
	# The [outputChannel] command (and underlying variable) have to
	# be kept in sync with the [configure -outfile] configuration
	# option ( and underlying variable Option(-outfile) ).  This is
	# accomplished with a write trace on Option(-outfile) that will
	# update [outputChannel] whenver a new value is written.  That
	# much is easy.
	#
	# The trick is that in order to maintain compatibility with
	# version 1 of tcltest, we must allow every configuration option
	# to get its inital value from command line arguments.  This is
	# accomplished by setting initial read traces on all the
	# configuration options to parse the command line option the first
	# time they are read.  These traces are cancelled whenever the
	# program itself calls [configure].
	# 
	# OK, then so to support tcltest 1 compatibility, it seems we want
	# to get the return from [outputFile] to trigger the read traces,
	# just in case.
	#
	# BUT!  A little known feature of Tcl variable traces is that 
	# traces are disabled during the handling of other traces.  So,
	# if we trigger read traces on Option(-outfile) and that triggers
	# command line parsing which turns around and sets an initial
	# value for Option(-outfile) -- <whew!> -- the write trace that
	# would keep [outputChannel] in sync with that new initial value
	# would not fire!
	#
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
    proc configure args {
	if {[llength $args] > 1} {
	    RemoveAutoConfigureTraces
	}
	set code [catch {Configure {*}$args} msg]
	return -code $code $msg
    }

    proc AcceptVerbose { level } {
	set level [AcceptList $level]
	set levelMap {
	    l list
	    p pass
	    b body
	    s skip
	    t start
	    e error
	    l line
	    m msec
	    u usec
	}
	set levelRegexp "^([join [dict values $levelMap] |])\$"
	if {[llength $level] == 1} {
	    if {![regexp $levelRegexp $level]} {
		# translate single characters abbreviations to expanded list

		set level [string map $levelMap [split $level {}]]
	    }
	}
	set valid [list]
	foreach v $level {
	    if {[regexp $levelRegexp $v]} {
		lappend valid $v
	    }
	}
	return $valid
    }

    proc IsVerbose {level} {
	variable Option
	return [expr {[lsearch -exact $Option(-verbose) $level] >= 0}]
    }

    # Default verbosity is to show bodies of failed tests
    Option -verbose {body error} {
	Takes any combination of the values 'p', 's', 'b', 't', 'e' and 'l'.
	Test suite will display all passed tests if 'p' is specified, all
	skipped tests if 's' is specified, the bodies of failed tests if
	'b' is specified, and when tests start if 't' is specified.
	ErrorInfo is displayed if 'e' is specified. Source file line
	information of failed tests is displayed if 'l' is specified.
    } AcceptVerbose verbose

    # Match and skip patterns default to the empty list, except for
    # matchFiles, which defaults to all .test files in the
    # testsDirectory and matchDirectories, which defaults to all
    # directories.
    Option -match * {







|


<
<
<
<
<
<
<
<
<
<
<
<

|

>
|




|








|









|







604
605
606
607
608
609
610
611
612
613












614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    proc configure args {
	if {[llength $args] > 1} {
	    RemoveAutoConfigureTraces
	}
	set code [catch {Configure {*}$args} msg]
	return -code $code $msg
    }
    
    proc AcceptVerbose { level } {
	set level [AcceptList $level]












	if {[llength $level] == 1} {
	    if {![regexp {^(pass|body|skip|start|error|line)$} $level]} {
		# translate single characters abbreviations to expanded list
		set level [string map {p pass b body s skip t start e error l line} \
			[split $level {}]]
	    }
	}
	set valid [list]
	foreach v $level {
	    if {[regexp {^(pass|body|skip|start|error|line)$} $v]} {
		lappend valid $v
	    }
	}
	return $valid
    }

    proc IsVerbose {level} {
	variable Option
	return [expr {[lsearch -exact $Option(-verbose) $level] != -1}]
    }

    # Default verbosity is to show bodies of failed tests
    Option -verbose {body error} {
	Takes any combination of the values 'p', 's', 'b', 't', 'e' and 'l'.
	Test suite will display all passed tests if 'p' is specified, all
	skipped tests if 's' is specified, the bodies of failed tests if
	'b' is specified, and when tests start if 't' is specified.
	ErrorInfo is displayed if 'e' is specified. Source file line
	information of failed tests is displayed if 'l' is specified. 
    } AcceptVerbose verbose

    # Match and skip patterns default to the empty list, except for
    # matchFiles, which defaults to all .test files in the
    # testsDirectory and matchDirectories, which defaults to all
    # directories.
    Option -match * {
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
    # debug output doesn't get printed by default; debug level 1 spits
    # up only the tests that were skipped because they didn't match or
    # were specifically skipped.  A debug level of 2 would spit up the
    # tcltest variables and flags provided; a debug level of 3 causes
    # some additional output regarding operations of the test harness.
    # The tcltest package currently implements only up to debug level 3.
    Option -debug 0 {
	Internal debug level
    } AcceptInteger debug

    proc SetSelectedConstraints args {
	variable Option
	foreach c $Option(-constraints) {
	    testConstraint $c 1
	}







|







683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
    # debug output doesn't get printed by default; debug level 1 spits
    # up only the tests that were skipped because they didn't match or
    # were specifically skipped.  A debug level of 2 would spit up the
    # tcltest variables and flags provided; a debug level of 3 causes
    # some additional output regarding operations of the test harness.
    # The tcltest package currently implements only up to debug level 3.
    Option -debug 0 {
	Internal debug level 
    } AcceptInteger debug

    proc SetSelectedConstraints args {
	variable Option
	foreach c $Option(-constraints) {
	    testConstraint $c 1
	}
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
	    if {$c ni $Option(-constraints)} {
		testConstraint $c 0
	    }
	}
    }
    Option -limitconstraints 0 {
	whether to run only tests with the constraints
    } AcceptBoolean limitConstraints
    trace add variable Option(-limitconstraints) write \
	    [namespace code {ClearUnselectedConstraints ;#}]

    # A test application has to know how to load the tested commands
    # into the interpreter.
    Option -load {} {
	Specifies the script to load the tested commands.
    } AcceptScript loadScript

    # Default is to run each test file in a separate process
    Option -singleproc 0 {
	whether to run all tests in one process
    } AcceptBoolean singleProcess

    proc AcceptTemporaryDirectory { directory } {
	set directory [AcceptAbsolutePath $directory]
	if {![file exists $directory]} {
	    file mkdir $directory
	}
	set directory [AcceptDirectory $directory]







|












|







711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
	    if {$c ni $Option(-constraints)} {
		testConstraint $c 0
	    }
	}
    }
    Option -limitconstraints 0 {
	whether to run only tests with the constraints
    } AcceptBoolean limitConstraints 
    trace add variable Option(-limitconstraints) write \
	    [namespace code {ClearUnselectedConstraints ;#}]

    # A test application has to know how to load the tested commands
    # into the interpreter.
    Option -load {} {
	Specifies the script to load the tested commands.
    } AcceptScript loadScript

    # Default is to run each test file in a separate process
    Option -singleproc 0 {
	whether to run all tests in one process
    } AcceptBoolean singleProcess 

    proc AcceptTemporaryDirectory { directory } {
	set directory [AcceptAbsolutePath $directory]
	if {![file exists $directory]} {
	    file mkdir $directory
	}
	set directory [AcceptDirectory $directory]
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
    # errors go to stderr by default
    Option -errfile stderr {
	Send errors from test runs to the specified file.
    } AcceptOutFile errorFile
    trace add variable Option(-errfile) write \
	    [namespace code {errorChannel $Option(-errfile) ;#}]

    proc loadIntoChildInterpreter {child args} {
	variable Version
	interp eval $child [package ifneeded tcltest $Version]
	interp eval $child "tcltest::configure {*}{$args}"
	interp alias $child ::tcltest::ReportToParent \
	    {} ::tcltest::ReportedFromChild
    }
    proc ReportedFromChild {total passed skipped failed because newfiles} {
	variable numTests
	variable skippedBecause
	variable createdNewFiles
	incr numTests(Total)   $total
	incr numTests(Passed)  $passed
	incr numTests(Skipped) $skipped
	incr numTests(Failed)  $failed







|

|
|
|
|

|







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
    # errors go to stderr by default
    Option -errfile stderr {
	Send errors from test runs to the specified file.
    } AcceptOutFile errorFile
    trace add variable Option(-errfile) write \
	    [namespace code {errorChannel $Option(-errfile) ;#}]

    proc loadIntoSlaveInterpreter {slave args} {
	variable Version
	interp eval $slave [package ifneeded tcltest $Version]
	interp eval $slave "tcltest::configure {*}{$args}"
	interp alias $slave ::tcltest::ReportToMaster \
	    {} ::tcltest::ReportedFromSlave
    }
    proc ReportedFromSlave {total passed skipped failed because newfiles} {
	variable numTests
	variable skippedBecause
	variable createdNewFiles
	incr numTests(Total)   $total
	incr numTests(Passed)  $passed
	incr numTests(Skipped) $skipped
	incr numTests(Failed)  $failed
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
    variable testConstraints
    variable Option
    DebugPuts 3 "entering testConstraint $constraint $value"
    if {[llength [info level 0]] == 2} {
	return $testConstraints($constraint)
    }
    # Check for boolean values
    if {[catch {expr {$value && 1}} msg]} {
	return -code error $msg
    }
    if {[limitConstraints] && ($constraint ni $Option(-constraints))} {
	set value 0
    }
    set testConstraints($constraint) $value
}







|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
    variable testConstraints
    variable Option
    DebugPuts 3 "entering testConstraint $constraint $value"
    if {[llength [info level 0]] == 2} {
	return $testConstraints($constraint)
    }
    # Check for boolean values
    if {[catch {expr {$value && $value}} msg]} {
	return -code error $msg
    }
    if {[limitConstraints] && ($constraint ni $Option(-constraints))} {
	set value 0
    }
    set testConstraints($constraint) $value
}
1251
1252
1253
1254
1255
1256
1257




1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
    ConstraintInitializer userInteraction {format 0}

    # Some tests must be skipped if the interpreter is not in
    # interactive mode

    ConstraintInitializer interactive \
	    {expr {[info exists ::tcl_interactive] && $::tcl_interactive}}





    # Some tests can only be run if the installation came from a CD
    # image instead of a web image.  Some tests must be skipped if you
    # are running as root on Unix.  Other tests can only be run if you
    # are running as root on Unix.

    ConstraintInitializer root {expr \
	    {($::tcl_platform(platform) eq "unix") &&
		    ($::tcl_platform(user) in {root {}})}}
    ConstraintInitializer notRoot {expr {![testConstraint root]}}

    # Set nonBlockFiles constraint: 1 means this platform supports
    # setting files into nonblocking mode.

    ConstraintInitializer nonBlockFiles {
	    set code [expr {[catch {set f [open defs r]}]
		    || [catch {fconfigure $f -blocking off}]}]
	    catch {close $f}
	    set code
    }

    # Set asyncPipeClose constraint: 1 means this platform supports
    # async flush and async close on a pipe.
    #
    # Test for SCO Unix - cannot run async flushing tests because a
    # potential problem with select is apparently interfering.
    # (Mark Diekhans).

    ConstraintInitializer asyncPipeClose {expr {
	    !([string equal unix $::tcl_platform(platform)]
	    && ([catch {exec uname -X | fgrep {Release = 3.2v}}] == 0))}}

    # Test to see if we have a broken version of sprintf with respect
    # to the "e" format of floating-point numbers.

    ConstraintInitializer eformat {string equal [format %g 5e-5] 5e-05}








>
>
>
>















|
|












|







1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
    ConstraintInitializer userInteraction {format 0}

    # Some tests must be skipped if the interpreter is not in
    # interactive mode

    ConstraintInitializer interactive \
	    {expr {[info exists ::tcl_interactive] && $::tcl_interactive}}

    # Skip slow tests (to enable slow tests add parameter `-constraints slowTest`)

    ConstraintInitializer slowTest {format 0}

    # Some tests can only be run if the installation came from a CD
    # image instead of a web image.  Some tests must be skipped if you
    # are running as root on Unix.  Other tests can only be run if you
    # are running as root on Unix.

    ConstraintInitializer root {expr \
	    {($::tcl_platform(platform) eq "unix") &&
		    ($::tcl_platform(user) in {root {}})}}
    ConstraintInitializer notRoot {expr {![testConstraint root]}}

    # Set nonBlockFiles constraint: 1 means this platform supports
    # setting files into nonblocking mode.

    ConstraintInitializer nonBlockFiles {
	    set code [expr {[catch {set f [open defs r]}] 
		    || [catch {chan configure $f -blocking off}]}]
	    catch {close $f}
	    set code
    }

    # Set asyncPipeClose constraint: 1 means this platform supports
    # async flush and async close on a pipe.
    #
    # Test for SCO Unix - cannot run async flushing tests because a
    # potential problem with select is apparently interfering.
    # (Mark Diekhans).

    ConstraintInitializer asyncPipeClose {expr {
	    !([string equal unix $::tcl_platform(platform)] 
	    && ([catch {exec uname -X | fgrep {Release = 3.2v}}] == 0))}}

    # Test to see if we have a broken version of sprintf with respect
    # to the "e" format of floating-point numbers.

    ConstraintInitializer eformat {string equal [format %g 5e-5] 5e-05}

1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
#                       optional; default is {}.
#   output -            Expected output sent to stdout.  This attribute
#                       is optional; default is {}.
#   errorOutput -       Expected output sent to stderr.  This attribute
#                       is optional; default is {}.
#   returnCodes -       Expected return codes.  This attribute is
#                       optional; default is {0 2}.
#   errorCode -         Expected error code.  This attribute is
#                       optional; default is {*}. It is a glob pattern.
#                       If given, returnCodes defaults to {1}.
#   setup -             Code to run before $script (above).  This
#                       attribute is optional; default is {}.
#   cleanup -           Code to run after $script (above).  This
#                       attribute is optional; default is {}.
#   match -             specifies type of matching to do on result,
#                       output, errorOutput; this must be a string
#			previously registered by a call to [customMatch].







<
<
<







1830
1831
1832
1833
1834
1835
1836



1837
1838
1839
1840
1841
1842
1843
#                       optional; default is {}.
#   output -            Expected output sent to stdout.  This attribute
#                       is optional; default is {}.
#   errorOutput -       Expected output sent to stderr.  This attribute
#                       is optional; default is {}.
#   returnCodes -       Expected return codes.  This attribute is
#                       optional; default is {0 2}.



#   setup -             Code to run before $script (above).  This
#                       attribute is optional; default is {}.
#   cleanup -           Code to run after $script (above).  This
#                       attribute is optional; default is {}.
#   match -             specifies type of matching to do on result,
#                       output, errorOutput; this must be a string
#			previously registered by a call to [customMatch].
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930

    FillFilesExisted
    incr testLevel

    # Pre-define everything to null except output and errorOutput.  We
    # determine whether or not to trap output based on whether or not
    # these variables (output & errorOutput) are defined.
    lassign {} constraints setup cleanup body result returnCodes errorCode match

    # Set the default match mode
    set match exact

    # Set the default match values for return codes (0 is the standard
    # expected return value if everything went well; 2 represents
    # 'return' being used in the test script).
    set returnCodes [list 0 2]

    # Set the default error code pattern
    set errorCode "*"

    # The old test format can't have a 3rd argument (constraints or
    # script) that starts with '-'.
    if {[string match -* [lindex $args 0]] || ([llength $args] <= 1)} {
	if {[llength $args] == 1} {
	    set list [SubstArguments [lindex $args 0]]
	    foreach {element value} $list {
		set testAttributes($element) $value
	    }
	    foreach item {constraints match setup body cleanup \
		    result returnCodes errorCode output errorOutput} {
		if {[info exists testAttributes(-$item)]} {
		    set testAttributes(-$item) [uplevel 1 \
			    ::concat $testAttributes(-$item)]
		}
	    }
	} else {
	    array set testAttributes $args
	}

	set validFlags {-setup -cleanup -body -result -returnCodes \
		-errorCode -match -output -errorOutput -constraints}

	foreach flag [array names testAttributes] {
	    if {$flag ni $validFlags} {
		incr testLevel -1
		set sorted [lsort $validFlags]
		set options [join [lrange $sorted 0 end-1] ", "]
		append options ", or [lindex $sorted end]"







|









<
<
<









|










|







1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887



1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915

    FillFilesExisted
    incr testLevel

    # Pre-define everything to null except output and errorOutput.  We
    # determine whether or not to trap output based on whether or not
    # these variables (output & errorOutput) are defined.
    lassign {} constraints setup cleanup body result returnCodes match

    # Set the default match mode
    set match exact

    # Set the default match values for return codes (0 is the standard
    # expected return value if everything went well; 2 represents
    # 'return' being used in the test script).
    set returnCodes [list 0 2]




    # The old test format can't have a 3rd argument (constraints or
    # script) that starts with '-'.
    if {[string match -* [lindex $args 0]] || ([llength $args] <= 1)} {
	if {[llength $args] == 1} {
	    set list [SubstArguments [lindex $args 0]]
	    foreach {element value} $list {
		set testAttributes($element) $value
	    }
	    foreach item {constraints match setup body cleanup \
		    result returnCodes output errorOutput} {
		if {[info exists testAttributes(-$item)]} {
		    set testAttributes(-$item) [uplevel 1 \
			    ::concat $testAttributes(-$item)]
		}
	    }
	} else {
	    array set testAttributes $args
	}

	set validFlags {-setup -cleanup -body -result -returnCodes \
		-match -output -errorOutput -constraints}

	foreach flag [array names testAttributes] {
	    if {$flag ni $validFlags} {
		incr testLevel -1
		set sorted [lsort $validFlags]
		set options [join [lrange $sorted 0 end-1] ", "]
		append options ", or [lindex $sorted end]"
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
		    must be $values"
	}

	# Replace symbolic valies supplied for -returnCodes
	foreach {strcode numcode} {ok 0 normal 0 error 1 return 2 break 3 continue 4} {
	    set returnCodes [string map -nocase [list $strcode $numcode] $returnCodes]
	}
        # errorCode without returnCode 1 is meaningless
        if {$errorCode ne "*" && 1 ni $returnCodes} {
            set returnCodes 1
        }
    } else {
	# This is parsing for the old test command format; it is here
	# for backward compatibility.
	set result [lindex $args end]
	if {[llength $args] == 2} {
	    set body [lindex $args 0]
	} elseif {[llength $args] == 3} {







<
<
<
<







1933
1934
1935
1936
1937
1938
1939




1940
1941
1942
1943
1944
1945
1946
		    must be $values"
	}

	# Replace symbolic valies supplied for -returnCodes
	foreach {strcode numcode} {ok 0 normal 0 error 1 return 2 break 3 continue 4} {
	    set returnCodes [string map -nocase [list $strcode $numcode] $returnCodes]
	}




    } else {
	# This is parsing for the old test command format; it is here
	# for backward compatibility.
	set result [lindex $args end]
	if {[llength $args] == 2} {
	    set body [lindex $args 0]
	} elseif {[llength $args] == 3} {
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
    }

    if {[Skipped $name $constraints]} {
	incr testLevel -1
	return
    }

    # Save information about the core file.
    if {[preserveCore]} {
	if {[file exists [file join [workingDirectory] core]]} {
	    set coreModTime [file mtime [file join [workingDirectory] core]]
	}
    }

    # First, run the setup script (or a hook if it presents):
    if {[set cmd [namespace which -command [namespace current]::SetupTest]] ne ""} {
	set setup [list $cmd $setup]
    }
    set processTest 1
    set code [catch {uplevel 1 $setup} setupMsg]
    if {$code == 1} {
	set errorInfo(setup) $::errorInfo
	set errorCodeRes(setup) $::errorCode
	if {$errorCodeRes(setup) eq "BYPASS-SKIPPED-TEST"} {
	    _noticeSkipped $name $setupMsg
	    set processTest [set code 0]
	}
    }
    set setupFailure [expr {$code != 0}]

    # Only run the test body if the setup was successful
    if {$processTest && !$setupFailure} {

	# Register startup time
	if {[IsVerbose msec] || [IsVerbose usec]} {
	    set timeStart [clock microseconds]
	}

	# Verbose notification of $body start
	if {[IsVerbose start]} {
	    puts [outputChannel] "---- $name start"
	    flush [outputChannel]
	}

	set command [list [namespace origin RunTest] $name $body]
	if {[info exists output] || [info exists errorOutput]} {
	    set testResult [uplevel 1 [list [namespace origin Eval] $command 0]]
	} else {
	    set testResult [uplevel 1 [list [namespace origin Eval] $command 1]]
	}
	lassign $testResult actualAnswer returnCode
	if {$returnCode == 1} {
	    set errorInfo(body) $::errorInfo
	    set errorCodeRes(body) $::errorCode
	    if {$errorCodeRes(body) eq "BYPASS-SKIPPED-TEST"} {
		_noticeSkipped $name $actualAnswer
		set processTest [set returnCode 0]
	    }
	}
    }

    # check if the return code matched the expected return code
    set codeFailure 0
    if {$processTest && !$setupFailure && ($returnCode ni $returnCodes)} {
	set codeFailure 1
    }
    set errorCodeFailure 0
    if {$processTest && !$setupFailure && !$codeFailure && $returnCode == 1 && \
                ![string match $errorCode $errorCodeRes(body)]} {
	set errorCodeFailure 1
    }

    # If expected output/error strings exist, we have to compare
    # them.  If the comparison fails, then so did the test.
    set outputFailure 0
    variable outData
    if {$processTest && [info exists output] && !$codeFailure} {
	if {[set outputCompare [catch {
	    CompareStrings $outData $output $match
	} outputMatch]] == 0} {
	    set outputFailure [expr {!$outputMatch}]
	} else {
	    set outputFailure 1
	}
    }

    set errorFailure 0
    variable errData
    if {$processTest && [info exists errorOutput] && !$codeFailure} {
	if {[set errorCompare [catch {
	    CompareStrings $errData $errorOutput $match
	} errorMatch]] == 0} {
	    set errorFailure [expr {!$errorMatch}]
	} else {
	    set errorFailure 1
	}
    }

    # check if the answer matched the expected answer
    # Only check if we ran the body of the test (no setup failure)
    if {!$processTest} {
    	set scriptFailure 0
    } elseif {$setupFailure || $codeFailure} {
	set scriptFailure 0
    } elseif {[set scriptCompare [catch {
	CompareStrings $actualAnswer $result $match
    } scriptMatch]] == 0} {
	set scriptFailure [expr {!$scriptMatch}]
    } else {
	set scriptFailure 1
    }

    # Always run the cleanup script (or a hook if it presents):
    if {[set cmd [namespace which -command [namespace current]::CleanupTest]] ne ""} {
	set cleanup [list $cmd $cleanup]
    }
    set code [catch {uplevel 1 $cleanup} cleanupMsg]
    if {$code == 1} {
	set errorInfo(cleanup) $::errorInfo
	set errorCodeRes(cleanup) $::errorCode
    }
    set cleanupFailure [expr {$code != 0}]

    set coreFailure 0
    set coreMsg ""
    # check for a core file first - if one was created by the test,
    # then the test failed
    if {[preserveCore]} {
	if {[file exists [file join [workingDirectory] core]]} {
	    # There's only a test failure if there is a core file
	    # and (1) there previously wasn't one or (2) the new
	    # one is different from the old one.
	    if {[info exists coreModTime]} {
		if {$coreModTime != [file mtime \
			[file join [workingDirectory] core]]} {
		    set coreFailure 1
		}
	    } else {
		set coreFailure 1
	    }

	    if {([preserveCore] > 1) && ($coreFailure)} {
		append coreMsg "\nMoving file to:\
		    [file join [temporaryDirectory] core-$name]"
		catch {file rename -force -- \
		    [file join [workingDirectory] core] \
		    [file join [temporaryDirectory] core-$name]
		} msg
		if {$msg ne {}} {
		    append coreMsg "\nError:\
			Problem renaming core file: $msg"
		}
	    }
	}
    }

    if {[IsVerbose msec] || [IsVerbose usec]} {
	set t [expr {[clock microseconds] - $timeStart}]
	if {[IsVerbose usec]} {
	    puts [outputChannel] "++++ $name took $t μs"
	}
	if {[IsVerbose msec]} {
	    puts [outputChannel] "++++ $name took [expr {round($t/1000.)}] ms"
	}
    }

    # if skipped, it is safe to return here
    if {!$processTest} {
	incr testLevel -1
	return
    }

    # if we didn't experience any failures, then we passed
    variable numTests
    if {!($setupFailure || $cleanupFailure || $coreFailure
	    || $outputFailure || $errorFailure || $codeFailure
	    || $errorCodeFailure || $scriptFailure)} {
	if {$testLevel == 1} {
	    incr numTests(Passed)
	    if {[IsVerbose pass]} {
		puts [outputChannel] "++++ $name PASSED"
	    }
	}
	incr testLevel -1
	return
    }

    # We know the test failed, tally it...
    if {$testLevel == 1} {
	incr numTests(Failed)
    }

    # ... then report according to the type of failure
    variable currentFailure true
    if {![IsVerbose body]} {
	set body ""
    }
    puts [outputChannel] "\n"
    if {[IsVerbose line]} {
	if {![catch {set testFrame [info frame -1]}] &&
		[dict get $testFrame type] eq "source"} {
	    set testFile [dict get $testFrame file]
	    set testLine [dict get $testFrame line]
	} else {
	    set testFile [file normalize [uplevel 1 {info script}]]
	    if {[file readable $testFile]} {
		set testFd [open $testFile r]
		set testLine [expr {[lsearch -regexp \
			[split [read $testFd] "\n"] \
			"^\[ \t\]*test [string map {. \\.} $name] "] + 1}]
		close $testFd
	    }
	}
	if {[info exists testLine]} {
	    puts [outputChannel] "$testFile:$testLine: error: test failed:\
		    $name [string trim $description]"
	}
    }
    puts [outputChannel] "==== $name\
	    [string trim $description] FAILED"
    if {[string length $body]} {
	puts [outputChannel] "==== Contents of test case:"
	puts [outputChannel] $body
    }
    if {$setupFailure} {
	puts [outputChannel] "---- Test setup\
		failed:\n$setupMsg"
	if {[info exists errorInfo(setup)]} {
	    puts [outputChannel] "---- errorInfo(setup): $errorInfo(setup)"
	    puts [outputChannel] "---- errorCode(setup): $errorCodeRes(setup)"
	}
    }
    if {$processTest && $scriptFailure} {
	if {$scriptCompare} {
	    puts [outputChannel] "---- Error testing result: $scriptMatch"
	} else {
	    puts [outputChannel] "---- Result was:\n$actualAnswer"
	    puts [outputChannel] "---- Result should have been\
		    ($match matching):\n$result"
	}
    }
    if {$errorCodeFailure} {
	puts [outputChannel] "---- Error code was: '$errorCodeRes(body)'"
	puts [outputChannel] "---- Error code should have been: '$errorCode'"
    }
    if {$codeFailure} {
	switch -- $returnCode {
	    0 { set msg "Test completed normally" }
	    1 { set msg "Test generated error" }
	    2 { set msg "Test generated return exception" }
	    3 { set msg "Test generated break exception" }
	    4 { set msg "Test generated continue exception" }
	    default { set msg "Test generated exception" }
	}
	puts [outputChannel] "---- $msg; Return code was: $returnCode"
	puts [outputChannel] "---- Return code should have been\
		one of: $returnCodes"
	if {[IsVerbose error]} {
	    if {[info exists errorInfo(body)] && (1 ni $returnCodes)} {
		puts [outputChannel] "---- errorInfo: $errorInfo(body)"
		puts [outputChannel] "---- errorCode: $errorCodeRes(body)"
	    }
	}
    }
    if {$outputFailure} {
	if {$outputCompare} {
	    puts [outputChannel] "---- Error testing output: $outputMatch"
	} else {







|






|
<
<
<
<



|
<
<
<
<




|
<
<
<
<
<
















|
<
<
<
<





|


<
<
<
<
<





|











|











<
<
|









|
<
<
<



|




















|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|



















|




















|











|


|








<
<
<
<















|







1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968




1969
1970
1971
1972




1973
1974
1975
1976
1977





1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994




1995
1996
1997
1998
1999
2000
2001
2002





2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031


2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042



2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
















2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151




2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
    }

    if {[Skipped $name $constraints]} {
	incr testLevel -1
	return
    }

    # Save information about the core file.  
    if {[preserveCore]} {
	if {[file exists [file join [workingDirectory] core]]} {
	    set coreModTime [file mtime [file join [workingDirectory] core]]
	}
    }

    # First, run the setup script




    set code [catch {uplevel 1 $setup} setupMsg]
    if {$code == 1} {
	set errorInfo(setup) $::errorInfo
	set errorCode(setup) $::errorCode




    }
    set setupFailure [expr {$code != 0}]

    # Only run the test body if the setup was successful
    if {!$setupFailure} {






	# Verbose notification of $body start
	if {[IsVerbose start]} {
	    puts [outputChannel] "---- $name start"
	    flush [outputChannel]
	}

	set command [list [namespace origin RunTest] $name $body]
	if {[info exists output] || [info exists errorOutput]} {
	    set testResult [uplevel 1 [list [namespace origin Eval] $command 0]]
	} else {
	    set testResult [uplevel 1 [list [namespace origin Eval] $command 1]]
	}
	lassign $testResult actualAnswer returnCode
	if {$returnCode == 1} {
	    set errorInfo(body) $::errorInfo
	    set errorCode(body) $::errorCode




	}
    }

    # check if the return code matched the expected return code
    set codeFailure 0
    if {!$setupFailure && ($returnCode ni $returnCodes)} {
	set codeFailure 1
    }






    # If expected output/error strings exist, we have to compare
    # them.  If the comparison fails, then so did the test.
    set outputFailure 0
    variable outData
    if {[info exists output] && !$codeFailure} {
	if {[set outputCompare [catch {
	    CompareStrings $outData $output $match
	} outputMatch]] == 0} {
	    set outputFailure [expr {!$outputMatch}]
	} else {
	    set outputFailure 1
	}
    }

    set errorFailure 0
    variable errData
    if {[info exists errorOutput] && !$codeFailure} {
	if {[set errorCompare [catch {
	    CompareStrings $errData $errorOutput $match
	} errorMatch]] == 0} {
	    set errorFailure [expr {!$errorMatch}]
	} else {
	    set errorFailure 1
	}
    }

    # check if the answer matched the expected answer
    # Only check if we ran the body of the test (no setup failure)


    if {$setupFailure || $codeFailure} {
	set scriptFailure 0
    } elseif {[set scriptCompare [catch {
	CompareStrings $actualAnswer $result $match
    } scriptMatch]] == 0} {
	set scriptFailure [expr {!$scriptMatch}]
    } else {
	set scriptFailure 1
    }

    # Always run the cleanup script



    set code [catch {uplevel 1 $cleanup} cleanupMsg]
    if {$code == 1} {
	set errorInfo(cleanup) $::errorInfo
	set errorCode(cleanup) $::errorCode
    }
    set cleanupFailure [expr {$code != 0}]

    set coreFailure 0
    set coreMsg ""
    # check for a core file first - if one was created by the test,
    # then the test failed
    if {[preserveCore]} {
	if {[file exists [file join [workingDirectory] core]]} {
	    # There's only a test failure if there is a core file
	    # and (1) there previously wasn't one or (2) the new
	    # one is different from the old one.
	    if {[info exists coreModTime]} {
		if {$coreModTime != [file mtime \
			[file join [workingDirectory] core]]} {
		    set coreFailure 1
		}
	    } else {
		set coreFailure 1
	    }
	
	    if {([preserveCore] > 1) && ($coreFailure)} {
		append coreMsg "\nMoving file to:\
		    [file join [temporaryDirectory] core-$name]"
		catch {file rename -force -- \
		    [file join [workingDirectory] core] \
		    [file join [temporaryDirectory] core-$name]
		} msg
		if {$msg ne {}} {
		    append coreMsg "\nError:\
			Problem renaming core file: $msg"
		}
	    }
	}
    }

















    # if we didn't experience any failures, then we passed
    variable numTests
    if {!($setupFailure || $cleanupFailure || $coreFailure
	    || $outputFailure || $errorFailure || $codeFailure
	    || $scriptFailure)} {
	if {$testLevel == 1} {
	    incr numTests(Passed)
	    if {[IsVerbose pass]} {
		puts [outputChannel] "++++ $name PASSED"
	    }
	}
	incr testLevel -1
	return
    }

    # We know the test failed, tally it...
    if {$testLevel == 1} {
	incr numTests(Failed)
    }

    # ... then report according to the type of failure
    variable currentFailure true
    if {![IsVerbose body]} {
	set body ""
    }	
    puts [outputChannel] "\n"
    if {[IsVerbose line]} {
	if {![catch {set testFrame [info frame -1]}] &&
		[dict get $testFrame type] eq "source"} {
	    set testFile [dict get $testFrame file]
	    set testLine [dict get $testFrame line]
	} else {
	    set testFile [file normalize [uplevel 1 {info script}]]
	    if {[file readable $testFile]} {
		set testFd [open $testFile r]
		set testLine [expr {[lsearch -regexp \
			[split [read $testFd] "\n"] \
			"^\[ \t\]*test [string map {. \\.} $name] "] + 1}]
		close $testFd
	    }
	}
	if {[info exists testLine]} {
	    puts [outputChannel] "$testFile:$testLine: error: test failed:\
		    $name [string trim $description]"
	}
    }	
    puts [outputChannel] "==== $name\
	    [string trim $description] FAILED"
    if {[string length $body]} {
	puts [outputChannel] "==== Contents of test case:"
	puts [outputChannel] $body
    }
    if {$setupFailure} {
	puts [outputChannel] "---- Test setup\
		failed:\n$setupMsg"
	if {[info exists errorInfo(setup)]} {
	    puts [outputChannel] "---- errorInfo(setup): $errorInfo(setup)"
	    puts [outputChannel] "---- errorCode(setup): $errorCode(setup)"
	}
    }
    if {$scriptFailure} {
	if {$scriptCompare} {
	    puts [outputChannel] "---- Error testing result: $scriptMatch"
	} else {
	    puts [outputChannel] "---- Result was:\n$actualAnswer"
	    puts [outputChannel] "---- Result should have been\
		    ($match matching):\n$result"
	}
    }




    if {$codeFailure} {
	switch -- $returnCode {
	    0 { set msg "Test completed normally" }
	    1 { set msg "Test generated error" }
	    2 { set msg "Test generated return exception" }
	    3 { set msg "Test generated break exception" }
	    4 { set msg "Test generated continue exception" }
	    default { set msg "Test generated exception" }
	}
	puts [outputChannel] "---- $msg; Return code was: $returnCode"
	puts [outputChannel] "---- Return code should have been\
		one of: $returnCodes"
	if {[IsVerbose error]} {
	    if {[info exists errorInfo(body)] && (1 ni $returnCodes)} {
		puts [outputChannel] "---- errorInfo: $errorInfo(body)"
		puts [outputChannel] "---- errorCode: $errorCode(body)"
	    }
	}
    }
    if {$outputFailure} {
	if {$outputCompare} {
	    puts [outputChannel] "---- Error testing output: $outputMatch"
	} else {
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
		    been ($match matching):\n$errorOutput"
	}
    }
    if {$cleanupFailure} {
	puts [outputChannel] "---- Test cleanup failed:\n$cleanupMsg"
	if {[info exists errorInfo(cleanup)]} {
	    puts [outputChannel] "---- errorInfo(cleanup): $errorInfo(cleanup)"
	    puts [outputChannel] "---- errorCode(cleanup): $errorCodeRes(cleanup)"
	}
    }
    if {$coreFailure} {
	puts [outputChannel] "---- Core file produced while running\
		test!  $coreMsg"
    }
    puts [outputChannel] "==== $name FAILED\n"

    incr testLevel -1
    return
}

# Skip --
#
# Skips a running test and add a reason to skipped "constraints". Can be used
# to conditional intended abort of the test.
#
# Side Effects:  Maintains tally of total tests seen and tests skipped.
#
proc tcltest::Skip {reason} {
    return -code error -errorcode BYPASS-SKIPPED-TEST $reason
}

proc tcltest::_noticeSkipped {name reason} {
    variable testLevel
    variable numTests

    if {[IsVerbose skip]} {
	puts [outputChannel] "++++ $name SKIPPED: $reason"
    }

    if {$testLevel == 1} {
	incr numTests(Skipped)
	AddToSkippedBecause $reason
    }
}


# Skipped --
#
# Given a test name and it constraints, returns a boolean indicating
# whether the current configuration says the test should be skipped.
#
# Side Effects:  Maintains tally of total tests seen and tests skipped.







|











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204


























2205
2206
2207
2208
2209
2210
2211
		    been ($match matching):\n$errorOutput"
	}
    }
    if {$cleanupFailure} {
	puts [outputChannel] "---- Test cleanup failed:\n$cleanupMsg"
	if {[info exists errorInfo(cleanup)]} {
	    puts [outputChannel] "---- errorInfo(cleanup): $errorInfo(cleanup)"
	    puts [outputChannel] "---- errorCode(cleanup): $errorCode(cleanup)"
	}
    }
    if {$coreFailure} {
	puts [outputChannel] "---- Core file produced while running\
		test!  $coreMsg"
    }
    puts [outputChannel] "==== $name FAILED\n"

    incr testLevel -1
    return
}



























# Skipped --
#
# Given a test name and it constraints, returns a boolean indicating
# whether the current configuration says the test should be skipped.
#
# Side Effects:  Maintains tally of total tests seen and tests skipped.
2369
2370
2371
2372
2373
2374
2375
2376
2377






2378

2379
2380
2381
2382
2383
2384
2385
		    # store the constraint that kept the test from
		    # running
		    set constraints $constraint
		    break
		}
	    }
	}

	if {!$doTest} {






	    _noticeSkipped $name $constraints

	    return 1
	}
    }
    return 0
}

# RunTest --







|

>
>
>
>
>
>
|
>







2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
		    # store the constraint that kept the test from
		    # running
		    set constraints $constraint
		    break
		}
	    }
	}
	
	if {!$doTest} {
	    if {[IsVerbose skip]} {
		puts [outputChannel] "++++ $name SKIPPED: $constraints"
	    }

	    if {$testLevel == 1} {
		incr numTests(Skipped)
		AddToSkippedBecause $constraints
	    }
	    return 1
	}
    }
    return 0
}

# RunTest --
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
    # If there is no "memory" command (because memory debugging isn't
    # enabled), then don't attempt to use the command.

    if {[llength [info commands memory]] == 1} {
	memory tag $name
    }

    # run the test script (or a hook if it presents):
    if {[set cmd [namespace which -command [namespace current]::EvalTest]] ne ""} {
	set script [list $cmd $script]
    }
    set code [catch {uplevel 1 $script} actualAnswer]

    return [list $actualAnswer $code]
}

#####################################################################








<
<
<
<







2309
2310
2311
2312
2313
2314
2315




2316
2317
2318
2319
2320
2321
2322
    # If there is no "memory" command (because memory debugging isn't
    # enabled), then don't attempt to use the command.

    if {[llength [info commands memory]] == 1} {
	memory tag $name
    }





    set code [catch {uplevel 1 $script} actualAnswer]

    return [list $actualAnswer $code]
}

#####################################################################

2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
    variable originalTclPlatform
    variable coreModTime

    FillFilesExisted
    set testFileName [file tail [info script]]

    # Hook to handle reporting to a parent interpreter
    if {[llength [info commands [namespace current]::ReportToParent]]} {
	ReportToParent $numTests(Total) $numTests(Passed) $numTests(Skipped) \
	    $numTests(Failed) [array get skippedBecause] \
	    [array get createdNewFiles]
	set testSingleFile false
    }

    # Call the cleanup hook
    cleanupTestsHook







|
|







2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
    variable originalTclPlatform
    variable coreModTime

    FillFilesExisted
    set testFileName [file tail [info script]]

    # Hook to handle reporting to a parent interpreter
    if {[llength [info commands [namespace current]::ReportToMaster]]} {
	ReportToMaster $numTests(Total) $numTests(Passed) $numTests(Skipped) \
	    $numTests(Failed) [array get skippedBecause] \
	    [array get createdNewFiles]
	set testSingleFile false
    }

    # Call the cleanup hook
    cleanupTestsHook
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
	}
    }

    if {[llength $matchDirs] == 0} {
	DebugPuts 1 "No test directories remain after applying match\
		and skip patterns!"
    }
    return [lsort $matchDirs]
}

# tcltest::runAllTests --
#
#	prints output and sources test files according to the match and
#	skip patterns provided.  after sourcing test files, it goes on
#	to source all.tcl files in matching test subdirectories.
#
# Arguments:
#	shell being tested
#
# Results:
#	Whether there were any failures.
#
# Side effects:
#	None.

proc tcltest::runAllTests { {shell ""} } {
    variable testSingleFile
    variable numTestFiles







|












|







2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
	}
    }

    if {[llength $matchDirs] == 0} {
	DebugPuts 1 "No test directories remain after applying match\
		and skip patterns!"
    }
    return $matchDirs
}

# tcltest::runAllTests --
#
#	prints output and sources test files according to the match and
#	skip patterns provided.  after sourcing test files, it goes on
#	to source all.tcl files in matching test subdirectories.
#
# Arguments:
#	shell being tested
#
# Results:
#	None.
#
# Side effects:
#	None.

proc tcltest::runAllTests { {shell ""} } {
    variable testSingleFile
    variable numTestFiles
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
    # Run each of the specified tests
    foreach file [lsort [GetMatchingFiles]] {
	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]

	if {[singleProcess]} {
	    if {[catch {
		incr numTestFiles
		uplevel 1 [list ::source $file]
	    } msg]} {
		puts [outputChannel] "Test file error: $msg"
		# append the name of the test to a list to be reported
		# later
		lappend testFileFailures $file
	    }
	    if {$numTests(Failed) > 0} {
		set failFilesSet 1
	    }
	} else {
	    # Pass along our configuration to the child processes.
	    # EXCEPT for the -outfile, because the parent process
	    # needs to read and process output of children.
	    set childargv [list]
	    foreach opt [Configure] {
		if {$opt eq "-outfile"} {continue}







<
|
|
<
<
<
<
<
<
<
<
<







2762
2763
2764
2765
2766
2767
2768

2769
2770









2771
2772
2773
2774
2775
2776
2777
    # Run each of the specified tests
    foreach file [lsort [GetMatchingFiles]] {
	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]

	if {[singleProcess]} {

	    incr numTestFiles
	    uplevel 1 [list ::source $file]









	} else {
	    # Pass along our configuration to the child processes.
	    # EXCEPT for the -outfile, because the parent process
	    # needs to read and process output of children.
	    set childargv [list]
	    foreach opt [Configure] {
		if {$opt eq "-outfile"} {continue}
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
			    } ""] $line null testFile \
			    Total Passed Skipped Failed]} {
			foreach index {Total Passed Skipped Failed} {
			    incr numTests($index) [set $index]
			}
			if {$Failed > 0} {
			    lappend failFiles $testFile
			    set failFilesSet 1
			}
		    } elseif {[regexp [join {
			    {^Number of tests skipped }
			    {for each constraint:}
			    {|^\t(\d+)\t(.+)$}
			    } ""] $line match skipped constraint]} {
			if {[string match \t* $match]} {







<







2796
2797
2798
2799
2800
2801
2802

2803
2804
2805
2806
2807
2808
2809
			    } ""] $line null testFile \
			    Total Passed Skipped Failed]} {
			foreach index {Total Passed Skipped Failed} {
			    incr numTests($index) [set $index]
			}
			if {$Failed > 0} {
			    lappend failFiles $testFile

			}
		    } elseif {[regexp [join {
			    {^Number of tests skipped }
			    {for each constraint:}
			    {|^\t(\d+)\t(.+)$}
			    } ""] $line match skipped constraint]} {
			if {[string match \t* $match]} {
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
    }

    # Checking for subdirectories in which to run tests
    foreach directory [GetMatchingDirectories [testsDirectory]] {
	set dir [file tail $directory]
	puts [outputChannel] [string repeat ~ 44]
	puts [outputChannel] "$dir test began at [eval $timeCmd]\n"

	uplevel 1 [list ::source [file join $directory all.tcl]]

	set endTime [eval $timeCmd]
	puts [outputChannel] "\n$dir test ended at $endTime"
	puts [outputChannel] ""
	puts [outputChannel] [string repeat ~ 44]
    }
    return [expr {[info exists testFileFailures] || [info exists failFilesSet]}]
}

#####################################################################

# Test utility procs - not used in tcltest, but may be useful for
# testing.








|

|





|







2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
    }

    # Checking for subdirectories in which to run tests
    foreach directory [GetMatchingDirectories [testsDirectory]] {
	set dir [file tail $directory]
	puts [outputChannel] [string repeat ~ 44]
	puts [outputChannel] "$dir test began at [eval $timeCmd]\n"
	
	uplevel 1 [list ::source [file join $directory all.tcl]]
	
	set endTime [eval $timeCmd]
	puts [outputChannel] "\n$dir test ended at $endTime"
	puts [outputChannel] ""
	puts [outputChannel] [string repeat ~ 44]
    }
    return
}

#####################################################################

# Test utility procs - not used in tcltest, but may be useful for
# testing.

3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094

    set fullName [file join $directory $name]

    DebugPuts 3 "[lindex [info level 0] 0]:\
	     putting ``$contents'' into $fullName"

    set fd [open $fullName w]
    fconfigure $fd -translation lf
    if {[package vsatisfies [package provide Tcl] 8.7-]} {
	fconfigure $fd -encoding utf-8
    }
    if {[string index $contents end] eq "\n"} {
	puts -nonewline $fd $contents
    } else {
	puts $fd $contents
    }
    close $fd








|
<
<
<







2977
2978
2979
2980
2981
2982
2983
2984



2985
2986
2987
2988
2989
2990
2991

    set fullName [file join $directory $name]

    DebugPuts 3 "[lindex [info level 0] 0]:\
	     putting ``$contents'' into $fullName"

    set fd [open $fullName w]
    chan configure $fd -translation lf



    if {[string index $contents end] eq "\n"} {
	puts -nonewline $fd $contents
    } else {
	puts $fd $contents
    }
    close $fd

3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    DebugPuts 3 "[lindex [info level 0] 0]: removing $fullName"
    set idx [lsearch -exact $filesMade $fullName]

    if {$idx < 0} {
	DebugDo 1 {
	    Warn "removeFile removing \"$fullName\":\n  not created by makeFile"
	}
    } else {
	set filesMade [lreplace $filesMade $idx $idx]
    }
    if {![file isfile $fullName]} {
	DebugDo 1 {
	    Warn "removeFile removing \"$fullName\":\n  not a file"
	}
    }
    if {[catch {file delete -- $fullName} msg ]} {
	DebugDo 1 {
	    Warn "removeFile removing \"$fullName\":\n  failed: $msg"
	}
    }
    return
}

# tcltest::makeDirectory --
#
# Create a new dir with the name <name>.
#
# If this dir hasn't been created via makeDirectory since the last time







>
|



<
<
|





|
<
<
<
<
<







3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025


3026
3027
3028
3029
3030
3031
3032





3033
3034
3035
3036
3037
3038
3039
    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    DebugPuts 3 "[lindex [info level 0] 0]: removing $fullName"
    set idx [lsearch -exact $filesMade $fullName]
    set filesMade [lreplace $filesMade $idx $idx]
    if {$idx == -1} {
	DebugDo 1 {
	    Warn "removeFile removing \"$fullName\":\n  not created by makeFile"
	}


    } 
    if {![file isfile $fullName]} {
	DebugDo 1 {
	    Warn "removeFile removing \"$fullName\":\n  not a file"
	}
    }
    return [file delete -- $fullName]





}

# tcltest::makeDirectory --
#
# Create a new dir with the name <name>.
#
# If this dir hasn't been created via makeDirectory since the last time
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    DebugPuts 3 "[lindex [info level 0] 0]: deleting $fullName"
    set idx [lsearch -exact $filesMade $fullName]
    set filesMade [lreplace $filesMade $idx $idx]
    if {$idx < 0} {
	DebugDo 1 {
	    Warn "removeDirectory removing \"$fullName\":\n  not created\
		    by makeDirectory"
	}
    }
    if {![file isdirectory $fullName]} {
	DebugDo 1 {
	    Warn "removeDirectory removing \"$fullName\":\n  not a directory"
	}
    }
    return [file delete -force -- $fullName]
}







|




|







3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    DebugPuts 3 "[lindex [info level 0] 0]: deleting $fullName"
    set idx [lsearch -exact $filesMade $fullName]
    set filesMade [lreplace $filesMade $idx $idx]
    if {$idx == -1} {
	DebugDo 1 {
	    Warn "removeDirectory removing \"$fullName\":\n  not created\
		    by makeDirectory"
	}
    } 
    if {![file isdirectory $fullName]} {
	DebugDo 1 {
	    Warn "removeDirectory removing \"$fullName\":\n  not a directory"
	}
    }
    return [file delete -force -- $fullName]
}
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
proc tcltest::viewFile {name {directory ""}} {
    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    set f [open $fullName]
    if {[package vsatisfies [package provide Tcl] 8.7-]} {
	fconfigure $f -encoding utf-8
    }
    set data [read -nonewline $f]
    close $f
    return $data
}

# tcltest::bytestring --
#
# Construct a string that consists of the requested sequence of bytes,
# as opposed to a string of properly formed UTF-8 characters.
# This allows the tester to
# 1. Create denormalized or improperly formed strings to pass to C
#    procedures that are supposed to accept strings with embedded NULL
#    bytes.
# 2. Confirm that a string result has a certain pattern of bytes, for
#    instance to confirm that "\xE0\0" in a Tcl script is stored
#    internally in UTF-8 as the sequence of bytes "\xC3\xA0\xC0\x80".
#
# Generally, it's a bad idea to examine the bytes in a Tcl string or to
# construct improperly formed strings in this manner, because it involves
# exposing that Tcl uses UTF-8 internally.
#
# This function doesn't work any more in Tcl 8.7, since the 'identity'
# is gone (TIP #345)
#
# Arguments:
#	string being converted
#
# Results:
#	result fom encoding
#
# Side effects:
#	None

if {![package vsatisfies [package provide Tcl] 8.7-]} {
    proc tcltest::bytestring {string} {
	return [encoding convertfrom identity $string]
    }
}

# tcltest::OpenFiles --
#
#	used in io tests, uses testchannel
#
# Arguments:







<
<
<














|
|





<
<
<









<
|
|
<







3120
3121
3122
3123
3124
3125
3126



3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147



3148
3149
3150
3151
3152
3153
3154
3155
3156

3157
3158

3159
3160
3161
3162
3163
3164
3165
proc tcltest::viewFile {name {directory ""}} {
    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    set f [open $fullName]



    set data [read -nonewline $f]
    close $f
    return $data
}

# tcltest::bytestring --
#
# Construct a string that consists of the requested sequence of bytes,
# as opposed to a string of properly formed UTF-8 characters.
# This allows the tester to
# 1. Create denormalized or improperly formed strings to pass to C
#    procedures that are supposed to accept strings with embedded NULL
#    bytes.
# 2. Confirm that a string result has a certain pattern of bytes, for
#    instance to confirm that "\xe0\0" in a Tcl script is stored
#    internally in UTF-8 as the sequence of bytes "\xc3\xa0\xc0\x80".
#
# Generally, it's a bad idea to examine the bytes in a Tcl string or to
# construct improperly formed strings in this manner, because it involves
# exposing that Tcl uses UTF-8 internally.
#



# Arguments:
#	string being converted
#
# Results:
#	result fom encoding
#
# Side effects:
#	None


proc tcltest::bytestring {string} {
    return [encoding convertfrom identity $string]

}

# tcltest::OpenFiles --
#
#	used in io tests, uses testchannel
#
# Arguments:
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
	    ## room to kill themselves off, otherwise the end up with a
	    ## massive queue of repeated events
	    after 1
	}
	testthread errorproc ThreadError
	return [llength [testthread names]]
    } elseif {[info commands thread::id] ne {}} {

	# Thread extension

	thread::errorproc ThreadNullError
	while {[llength [thread::names]] > 1} {
	    foreach tid [thread::names] {
		if {$tid != [mainThread]} {
		    catch {thread::send -async $tid {thread::exit}}







|







3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
	    ## room to kill themselves off, otherwise the end up with a
	    ## massive queue of repeated events
	    after 1
	}
	testthread errorproc ThreadError
	return [llength [testthread names]]
    } elseif {[info commands thread::id] ne {}} {
	
	# Thread extension

	thread::errorproc ThreadNullError
	while {[llength [thread::names]] > 1} {
	    foreach tid [thread::names] {
		if {$tid != [mainThread]} {
		    catch {thread::send -async $tid {thread::exit}}

Changes to library/tm.tcl.

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
# -*- tcl -*-
#
# Searching for Tcl Modules. Defines a procedure, declares it as the primary
# command for finding packages, however also uses the former 'package unknown'
# command as a fallback.
#
# Locates all possible packages in a directory via a less restricted glob. The
# targeted directory is derived from the name of the requested package, i.e.
# the TM scan will look only at directories which can contain the requested

# package. It will register all packages it found in the directory so that
# future requests have a higher chance of being fulfilled by the ifneeded
# database without having to come to us again.
#
# We do not remember where we have been and simply rescan targeted directories
# when invoked again. The reasoning is this:
#
# - The only way we get back to the same directory is if someone is trying to
#   [package require] something that wasn't there on the first scan.

#
#   Either
#   1) It is there now:  If we rescan, you get it; if not you don't.
#
#      This covers the possibility that the application asked for a package
#      late, and the package was actually added to the installation after the
#      application was started. It shoukld still be able to find it.

#
#   2) It still is not there: Either way, you don't get it, but the rescan
#      takes time. This is however an error case and we dont't care that much
#      about it
#
#   3) It was there the first time; but for some reason a "package forget" has
#      been run, and "package" doesn't know about it anymore.

#
#      This can be an indication that the application wishes to reload some
#      functionality. And should work as well.
#
# Note that this also strikes a balance between doing a glob targeting a
# single package, and thus most likely requiring multiple globs of the same
# directory when the application is asking for many packages, and trying to
# glob for _everything_ in all subdirectories when looking for a package,
# which comes with a heavy startup cost.
#
# We scan for regular packages only if no satisfying module was found.

namespace eval ::tcl::tm {
    # Default paths. None yet.

    variable paths {}


|
|
|

|
|
|
>
|
|
|

|
|

|
|
>




|
|
|
>

|
|
|

|
|
>

|
|

|
|
|
|
|







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
# -*- tcl -*-
#
# Searching for Tcl Modules. Defines a procedure, declares it as the
# primary command for finding packages, however also uses the former
# 'package unknown' command as a fallback.
#
# Locates all possible packages in a directory via a less restricted
# glob. The targeted directory is derived from the name of the
# requested package. I.e. the TM scan will look only at directories
# which can contain the requested package. It will register all
# packages it found in the directory so that future requests have a
# higher chance of being fulfilled by the ifneeded database without
# having to come to us again.
#
# We do not remember where we have been and simply rescan targeted
# directories when invoked again. The reasoning is this:
#
# - The only way we get back to the same directory is if someone is
#   trying to [package require] something that wasn't there on the
#   first scan.
#
#   Either
#   1) It is there now:  If we rescan, you get it; if not you don't.
#
#      This covers the possibility that the application asked for a
#      package late, and the package was actually added to the
#      installation after the application was started. It shoukld
#      still be able to find it.
#
#   2) It still is not there: Either way, you don't get it, but the
#      rescan takes time. This is however an error case and we dont't
#      care that much about it
#
#   3) It was there the first time; but for some reason a "package
#      forget" has been run, and "package" doesn't know about it
#      anymore.
#
#      This can be an indication that the application wishes to reload
#      some functionality. And should work as well.
#
# Note that this also strikes a balance between doing a glob targeting
# a single package, and thus most likely requiring multiple globs of
# the same directory when the application is asking for many packages,
# and trying to glob for _everything_ in all subdirectories when
# looking for a package, which comes with a heavy startup cost.
#
# We scan for regular packages only if no satisfying module was found.

namespace eval ::tcl::tm {
    # Default paths. None yet.

    variable paths {}
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
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#
# Arguments
#	cmd -	The subcommand to execute
#	args -	The paths to add/remove. Must not appear querying the
#		path with 'list'.
#
# Results
#	No result for subcommands 'add' and 'remove'. A list of paths for
#	'list'.
#
# Sideeffects
#	The subcommands 'add' and 'remove' manipulate the list of paths to
#	search for Tcl Modules. The subcommand 'list' has no sideeffects.


proc ::tcl::tm::add {args} {
    # PART OF THE ::tcl::tm::path ENSEMBLE
    #
    # The path is added at the head to the list of module paths.
    #
    # The command enforces the restriction that no path may be an ancestor
    # directory of any other path on the list. If the new path violates this
    # restriction an error wil be raised.
    #
    # If the path is already present as is no error will be raised and no
    # action will be taken.

    variable paths

    # We use a copy of the path as source during validation, and extend it as
    # well. Because we not only have to detect if the new paths are bogus with
    # respect to the existing paths, but also between themselves. Otherwise we

    # can still add bogus paths, by specifying them in a single call. This
    # makes the use of the new paths simpler as well, a trivial assignment of
    # the collected paths to the official state var.

    set newpaths $paths
    foreach p $args {
	if {$p in $newpaths} {
	    # Ignore a path already on the list.
	    continue
	}

	# Search for paths which are subdirectories of the new one. If there
	# are any then the new path violates the restriction about ancestors.


	set pos [lsearch -glob $newpaths ${p}/*]
	# Cannot use "in", we need the position for the message.
	if {$pos >= 0} {
	    return -code error \
		"$p is ancestor of existing module path [lindex $newpaths $pos]."
	}

	# Now look for existing paths which are ancestors of the new one. This
	# reverse question forces us to loop over the existing paths, as each
	# element is the pattern, not the new path :(


	foreach ep $newpaths {
	    if {[string match ${ep}/* $p]} {
		return -code error \
		    "$p is subdirectory of existing module path $ep."
	    }
	}

	set newpaths [linsert $newpaths 0 $p]
    }

    # The validation of the input is complete and successful, and everything
    # in newpaths is either an old path, or added. We can now extend the
    # official list of paths, a simple assignment is sufficient.


    set paths $newpaths
    return
}

proc ::tcl::tm::remove {args} {
    # PART OF THE ::tcl::tm::path ENSEMBLE
    #
    # Removes the path from the list of module paths. The command is silently
    # ignored if the path is not on the list.

    variable paths

    foreach p $args {
	set pos [lsearch -exact $paths $p]
	if {$pos >= 0} {
	    set paths [lreplace $paths $pos $pos]
	}
    }
}








|
|


|
|
>

|




|
|
|

|
|



|
|
|
>
|
|
|


|





|
|
>








|
|
|
>











|
|
|
>





|


|
|



|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#
# Arguments
#	cmd -	The subcommand to execute
#	args -	The paths to add/remove. Must not appear querying the
#		path with 'list'.
#
# Results
#	No result for subcommands 'add' and 'remove'. A list of paths
#	for 'list'.
#
# Sideeffects
#	The subcommands 'add' and 'remove' manipulate the list of
#	paths to search for Tcl Modules. The subcommand 'list' has no
#	sideeffects.

proc ::tcl::tm::add {path args} {
    # PART OF THE ::tcl::tm::path ENSEMBLE
    #
    # The path is added at the head to the list of module paths.
    #
    # The command enforces the restriction that no path may be an
    # ancestor directory of any other path on the list. If the new
    # path violates this restriction an error wil be raised.
    #
    # If the path is already present as is no error will be raised and
    # no action will be taken.

    variable paths

    # We use a copy of the path as source during validation, and
    # extend it as well. Because we not only have to detect if the new
    # paths are bogus with respect to the existing paths, but also
    # between themselves. Otherwise we can still add bogus paths, by
    # specifying them in a single call. This makes the use of the new
    # paths simpler as well, a trivial assignment of the collected
    # paths to the official state var.

    set newpaths $paths
    foreach p [linsert $args 0 $path] {
	if {$p in $newpaths} {
	    # Ignore a path already on the list.
	    continue
	}

	# Search for paths which are subdirectories of the new one. If
	# there are any then the new path violates the restriction
	# about ancestors.

	set pos [lsearch -glob $newpaths ${p}/*]
	# Cannot use "in", we need the position for the message.
	if {$pos >= 0} {
	    return -code error \
		"$p is ancestor of existing module path [lindex $newpaths $pos]."
	}

	# Now look for existing paths which are ancestors of the new
	# one. This reverse question forces us to loop over the
	# existing paths, as each element is the pattern, not the new
	# path :(

	foreach ep $newpaths {
	    if {[string match ${ep}/* $p]} {
		return -code error \
		    "$p is subdirectory of existing module path $ep."
	    }
	}

	set newpaths [linsert $newpaths 0 $p]
    }

    # The validation of the input is complete and successful, and
    # everything in newpaths is either an old path, or added. We can
    # now extend the official list of paths, a simple assignment is
    # sufficient.

    set paths $newpaths
    return
}

proc ::tcl::tm::remove {path args} {
    # PART OF THE ::tcl::tm::path ENSEMBLE
    #
    # Removes the path from the list of module paths. The command is
    # silently ignored if the path is not on the list.

    variable paths

    foreach p [linsert $args 0 $path] {
	set pos [lsearch -exact $paths $p]
	if {$pos >= 0} {
	    set paths [lreplace $paths $pos $pos]
	}
    }
}

164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# Arguments
#	original	- Original [package unknown] procedure.
#	name		- Name of desired package.
#	version		- Version of desired package. Can be the
#			  empty string.
#	exact		- Either -exact or ommitted.
#
#	Name, version, and exact are used to determine satisfaction. The
#	original is called iff no satisfaction was achieved. The name is also
#	used to compute the directory to target in the search.

#
# Results
#	None.
#
# Sideeffects
#	May populate the package ifneeded database with additional provide
#	scripts.

proc ::tcl::tm::UnknownHandler {original name args} {
    # Import the list of paths to search for packages in module form.
    # Import the pattern used to check package names in detail.

    variable paths
    variable pkgpattern

    # Without paths to search we can do nothing. (Except falling back to the
    # regular search).

    if {[llength $paths]} {
	set pkgpath [string map {:: /} $name]
	set pkgroot [file dirname $pkgpath]
	if {$pkgroot eq "."} {
	    set pkgroot ""
	}

	# We don't remember a copy of the paths while looping. Tcl Modules are
	# unable to change the list while we are searching for them. This also
	# simplifies the loop, as we cannot get additional directories while

	# iterating over the list. A simple foreach is sufficient.

	set satisfied 0
	foreach path $paths {
	    if {![interp issafe] && ![file exists $path]} {
		continue
	    }
	    set currentsearchpath [file join $path $pkgroot]
	    if {![interp issafe] && ![file exists $currentsearchpath]} {
		continue
	    }
	    set strip [llength [file split $path]]

	    # We can't use glob in safe interps, so enclose the following in a
	    # catch statement, where we get the module files out of the
	    # subdirectories. In other words, Tcl Modules are not-functional
	    # in such an interpreter. This is the same as for the command
	    # "tclPkgUnknown", i.e. the search for regular packages.


	    catch {
		# We always look for _all_ possible modules in the current
		# path, to get the max result out of the glob.

		foreach file [glob -nocomplain -directory $currentsearchpath *.tm] {
		    set pkgfilename [join [lrange [file split $file] $strip end] ::]

		    if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} {
			# Ignore everything not matching our pattern for
			# package names.
			continue
		    }
		    if {[catch {package vcompare $pkgversion 0}]} {
			# Ignore everything where the version part is not
			# acceptable to "package vcompare".
			continue
		    }

		    if {[package ifneeded $pkgname $pkgversion] ne {}} {
			# There's already a provide script registered for
			# this version of this package.  Since all units of
			# code claiming to be the same version of the same
			# package ought to be identical, just stick with
			# the one we already have.
			continue
		    }

		    # We have found a candidate, generate a "provide script"
		    # for it, and remember it.  Note that we are using ::list

		    # to do this; locally [list] means something else without
		    # the namespace specifier.

		    # NOTE. When making changes to the format of the provide
		    # command generated below CHECK that the 'LOCATE'
		    # procedure in core file 'platform/shell.tcl' still
		    # understands it, or, if not, update its implementation
		    # appropriately.
		    #
		    # Right now LOCATE's implementation assumes that the path
		    # of the package file is the last element in the list.


		    package ifneeded $pkgname $pkgversion \
			"[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]"

		    # We abort in this unknown handler only if we got a
		    # satisfying candidate for the requested package.
		    # Otherwise we still have to fallback to the regular
		    # package search to complete the processing.


		    if {($pkgname eq $name)
			    && [package vsatisfies $pkgversion {*}$args]} {
			set satisfied 1

			# We do not abort the loop, and keep adding provide
			# scripts for every candidate in the directory, just
			# remember to not fall back to the regular search
			# anymore.
		    }
		}
	    }
	}

	if {$satisfied} {
	    return
	}
    }

    # Fallback to previous command, if existing.  See comment above about
    # ::list...

    if {[llength $original]} {
	uplevel 1 $original [::linsert $args 0 $name]
    }
}

# ::tcl::tm::Defaults --







|
|
|
>





|
|








|
|








|
|
|
>
|












|
|
|
|
|
>









|
|



|
|












|
|
>
|
|

|
|
|
|
|

|
|
>




|
|
|
|
>




<
|
|
|
|










|
|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# Arguments
#	original	- Original [package unknown] procedure.
#	name		- Name of desired package.
#	version		- Version of desired package. Can be the
#			  empty string.
#	exact		- Either -exact or ommitted.
#
#	Name, version, and exact are used to determine
#	satisfaction. The original is called iff no satisfaction was
#	achieved. The name is also used to compute the directory to
#	target in the search.
#
# Results
#	None.
#
# Sideeffects
#	May populate the package ifneeded database with additional
#	provide scripts.

proc ::tcl::tm::UnknownHandler {original name args} {
    # Import the list of paths to search for packages in module form.
    # Import the pattern used to check package names in detail.

    variable paths
    variable pkgpattern

    # Without paths to search we can do nothing. (Except falling back
    # to the regular search).

    if {[llength $paths]} {
	set pkgpath [string map {:: /} $name]
	set pkgroot [file dirname $pkgpath]
	if {$pkgroot eq "."} {
	    set pkgroot ""
	}

	# We don't remember a copy of the paths while looping. Tcl
	# Modules are unable to change the list while we are searching
	# for them. This also simplifies the loop, as we cannot get
	# additional directories while iterating over the list. A
	# simple foreach is sufficient.

	set satisfied 0
	foreach path $paths {
	    if {![interp issafe] && ![file exists $path]} {
		continue
	    }
	    set currentsearchpath [file join $path $pkgroot]
	    if {![interp issafe] && ![file exists $currentsearchpath]} {
		continue
	    }
	    set strip [llength [file split $path]]

	    # We can't use glob in safe interps, so enclose the following
	    # in a catch statement, where we get the module files out
	    # of the subdirectories. In other words, Tcl Modules are
	    # not-functional in such an interpreter. This is the same
	    # as for the command "tclPkgUnknown", i.e. the search for
	    # regular packages.

	    catch {
		# We always look for _all_ possible modules in the current
		# path, to get the max result out of the glob.

		foreach file [glob -nocomplain -directory $currentsearchpath *.tm] {
		    set pkgfilename [join [lrange [file split $file] $strip end] ::]

		    if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} {
			# Ignore everything not matching our pattern
			# for package names.
			continue
		    }
		    if {[catch {package vcompare $pkgversion 0}]} {
			# Ignore everything where the version part is
			# not acceptable to "package vcompare".
			continue
		    }

		    if {[package ifneeded $pkgname $pkgversion] ne {}} {
			# There's already a provide script registered for
			# this version of this package.  Since all units of
			# code claiming to be the same version of the same
			# package ought to be identical, just stick with
			# the one we already have.
			continue
		    }

		    # We have found a candidate, generate a "provide
		    # script" for it, and remember it.  Note that we
		    # are using ::list to do this; locally [list]
		    # means something else without the namespace
		    # specifier.

		    # NOTE. When making changes to the format of the
		    # provide command generated below CHECK that the
		    # 'LOCATE' procedure in core file
		    # 'platform/shell.tcl' still understands it, or,
		    # if not, update its implementation appropriately.
		    #
		    # Right now LOCATE's implementation assumes that
		    # the path of the package file is the last element
		    # in the list.

		    package ifneeded $pkgname $pkgversion \
			"[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]"

		    # We abort in this unknown handler only if we got
		    # a satisfying candidate for the requested
		    # package. Otherwise we still have to fallback to
		    # the regular package search to complete the
		    # processing.

		    if {($pkgname eq $name)
			    && [package vsatisfies $pkgversion {*}$args]} {
			set satisfied 1

			# We do not abort the loop, and keep adding
			# provide scripts for every candidate in the
			# directory, just remember to not fall back to
			# the regular search anymore.
		    }
		}
	    }
	}

	if {$satisfied} {
	    return
	}
    }

    # Fallback to previous command, if existing.  See comment above
    # about ::list...

    if {[llength $original]} {
	uplevel 1 $original [::linsert $args 0 $name]
    }
}

# ::tcl::tm::Defaults --
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#
# Sideeffects
#	May add paths to the list of defaults.

proc ::tcl::tm::Defaults {} {
    global env tcl_platform

    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    set exe [file normalize [info nameofexecutable]]

    # Note that we're using [::list], not [list] because [list] means
    # something other than [::list] in this namespace.
    roots [::list \
	    [file dirname [info library]] \
	    [file join [file dirname [file dirname $exe]] lib] \







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#
# Sideeffects
#	May add paths to the list of defaults.

proc ::tcl::tm::Defaults {} {
    global env tcl_platform

    lassign [split [info tclversion] .] major minor
    set exe [file normalize [info nameofexecutable]]

    # Note that we're using [::list], not [list] because [list] means
    # something other than [::list] in this namespace.
    roots [::list \
	    [file dirname [info library]] \
	    [file join [file dirname [file dirname $exe]] lib] \
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# Results
#	No result.
#
# Sideeffects
#	Calls 'path add' to paths to the list of module search paths.

proc ::tcl::tm::roots {paths} {
    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    foreach pa $paths {
	set p [file join $pa tcl$major]
	for {set n $minor} {$n >= 0} {incr n -1} {
	    set px [file join $p ${major}.${n}]
	    if {![interp issafe]} {set px [file normalize $px]}
	    path add $px
	}
	set px [file join $p site-tcl]
	if {![interp issafe]} {set px [file normalize $px]}
	path add $px
    }
    return
}

# Initialization. Set up the default paths, then insert the new handler into
# the chain.

if {![interp issafe]} {::tcl::tm::Defaults}







|




|



|





|
|

|
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# Results
#	No result.
#
# Sideeffects
#	Calls 'path add' to paths to the list of module search paths.

proc ::tcl::tm::roots {paths} {
    lassign [split [package present Tcl] .] major minor
    foreach pa $paths {
	set p [file join $pa tcl$major]
	for {set n $minor} {$n >= 0} {incr n -1} {
	    set px [file join $p ${major}.${n}]
	    if {![interp issafe]} { set px [file normalize $px] }
	    path add $px
	}
	set px [file join $p site-tcl]
	if {![interp issafe]} { set px [file normalize $px] }
	path add $px
    }
    return
}

# Initialization. Set up the default paths, then insert the new
# handler into the chain.

if {![interp issafe]} { ::tcl::tm::Defaults }

Changes to library/tzdata/Africa/Accra.

1
2
3
4
5

















































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan
}
set TZData(:Africa/Accra) $TZData(:Africa/Abidjan)


















































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Africa/Accra) {
    {-9223372036854775808 -52 0 LMT}
    {-1640995148 0 0 GMT}
    {-1556841600 1200 1 GMT}
    {-1546388400 0 0 GMT}
    {-1525305600 1200 1 GMT}
    {-1514852400 0 0 GMT}
    {-1493769600 1200 1 GMT}
    {-1483316400 0 0 GMT}
    {-1462233600 1200 1 GMT}
    {-1451780400 0 0 GMT}
    {-1430611200 1200 1 GMT}
    {-1420158000 0 0 GMT}
    {-1399075200 1200 1 GMT}
    {-1388622000 0 0 GMT}
    {-1367539200 1200 1 GMT}
    {-1357086000 0 0 GMT}
    {-1336003200 1200 1 GMT}
    {-1325550000 0 0 GMT}
    {-1304380800 1200 1 GMT}
    {-1293927600 0 0 GMT}
    {-1272844800 1200 1 GMT}
    {-1262391600 0 0 GMT}
    {-1241308800 1200 1 GMT}
    {-1230855600 0 0 GMT}
    {-1209772800 1200 1 GMT}
    {-1199319600 0 0 GMT}
    {-1178150400 1200 1 GMT}
    {-1167697200 0 0 GMT}
    {-1146614400 1200 1 GMT}
    {-1136161200 0 0 GMT}
    {-1115078400 1200 1 GMT}
    {-1104625200 0 0 GMT}
    {-1083542400 1200 1 GMT}
    {-1073089200 0 0 GMT}
    {-1051920000 1200 1 GMT}
    {-1041466800 0 0 GMT}
    {-1020384000 1200 1 GMT}
    {-1009930800 0 0 GMT}
    {-988848000 1200 1 GMT}
    {-978394800 0 0 GMT}
    {-957312000 1200 1 GMT}
    {-946858800 0 0 GMT}
    {-925689600 1200 1 GMT}
    {-915236400 0 0 GMT}
    {-894153600 1200 1 GMT}
    {-883700400 0 0 GMT}
    {-862617600 1200 1 GMT}
    {-852164400 0 0 GMT}
}

Changes to library/tzdata/Africa/Algiers.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Algiers) {
    {-9223372036854775808 732 0 LMT}
    {-2486592732 561 0 PMT}
    {-1855958961 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}




|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Algiers) {
    {-9223372036854775808 732 0 LMT}
    {-2486679072 561 0 PMT}
    {-1855958961 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}

Changes to library/tzdata/Africa/Casablanca.

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
120
121
122
123
124
125
126
127


128
129
130
131
132
133
134
135
136
137
138
139


140
141
142
143
144


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165




166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191


192
193
194
195
196
197
198
199
200
201

202
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Casablanca) {
    {-9223372036854775808 -1820 0 LMT}
    {-1773012580 0 0 +00}
    {-956361600 3600 1 +00}
    {-950490000 0 0 +00}
    {-942019200 3600 1 +00}
    {-761187600 0 0 +00}
    {-617241600 3600 1 +00}
    {-605149200 0 0 +00}
    {-81432000 3600 1 +00}
    {-71110800 0 0 +00}
    {141264000 3600 1 +00}
    {147222000 0 0 +00}
    {199756800 3600 1 +00}
    {207702000 0 0 +00}
    {231292800 3600 1 +00}
    {244249200 0 0 +00}
    {265507200 3600 1 +00}
    {271033200 0 0 +00}
    {448243200 3600 0 +01}
    {504918000 0 0 +00}
    {1212278400 3600 1 +00}
    {1220223600 0 0 +00}
    {1243814400 3600 1 +00}
    {1250809200 0 0 +00}
    {1272758400 3600 1 +00}
    {1281222000 0 0 +00}
    {1301788800 3600 1 +00}
    {1312066800 0 0 +00}
    {1335664800 3600 1 +00}
    {1342749600 0 0 +00}
    {1345428000 3600 1 +00}
    {1348970400 0 0 +00}
    {1367114400 3600 1 +00}
    {1373162400 0 0 +00}
    {1376100000 3600 1 +00}
    {1382839200 0 0 +00}
    {1396144800 3600 1 +00}
    {1403920800 0 0 +00}
    {1406944800 3600 1 +00}
    {1414288800 0 0 +00}
    {1427594400 3600 1 +00}
    {1434247200 0 0 +00}
    {1437271200 3600 1 +00}
    {1445738400 0 0 +00}
    {1459044000 3600 1 +00}
    {1465092000 0 0 +00}
    {1468116000 3600 1 +00}
    {1477792800 0 0 +00}
    {1490493600 3600 1 +00}
    {1495332000 0 0 +00}
    {1498960800 3600 1 +00}
    {1509242400 0 0 +00}
    {1521943200 3600 1 +00}
    {1526176800 0 0 +00}
    {1529200800 3600 1 +00}

    {1540695600 3600 0 +01}
    {1557021600 0 1 +01}
    {1560045600 3600 0 +01}


    {1587261600 0 1 +01}


    {1590890400 3600 0 +01}
    {1618106400 0 1 +01}
    {1621130400 3600 0 +01}
    {1648346400 0 1 +01}
    {1651975200 3600 0 +01}
    {1679191200 0 1 +01}
    {1682820000 3600 0 +01}
    {1710036000 0 1 +01}
    {1713060000 3600 0 +01}
    {1740276000 0 1 +01}
    {1743904800 3600 0 +01}
    {1771120800 0 1 +01}
    {1774144800 3600 0 +01}
    {1801965600 0 1 +01}
    {1804989600 3600 0 +01}
    {1832205600 0 1 +01}
    {1835834400 3600 0 +01}
    {1863050400 0 1 +01}
    {1866074400 3600 0 +01}
    {1893290400 0 1 +01}
    {1896919200 3600 0 +01}
    {1924135200 0 1 +01}
    {1927764000 3600 0 +01}
    {1954980000 0 1 +01}
    {1958004000 3600 0 +01}
    {1985220000 0 1 +01}
    {1988848800 3600 0 +01}
    {2016064800 0 1 +01}
    {2019088800 3600 0 +01}
    {2046304800 0 1 +01}
    {2049933600 3600 0 +01}
    {2077149600 0 1 +01}
    {2080778400 3600 0 +01}
    {2107994400 0 1 +01}

    {2111018400 3600 0 +01}
    {2138234400 0 1 +01}

    {2141863200 3600 0 +01}
    {2169079200 0 1 +01}




    {2172708000 3600 0 +01}




    {2199924000 0 1 +01}
    {2202948000 3600 0 +01}
    {2230164000 0 1 +01}
    {2233792800 3600 0 +01}
    {2261008800 0 1 +01}
    {2264032800 3600 0 +01}
    {2291248800 0 1 +01}
    {2294877600 3600 0 +01}
    {2322093600 0 1 +01}
    {2325722400 3600 0 +01}
    {2352938400 0 1 +01}
    {2355962400 3600 0 +01}
    {2383178400 0 1 +01}
    {2386807200 3600 0 +01}
    {2414023200 0 1 +01}
    {2417652000 3600 0 +01}
    {2444868000 0 1 +01}
    {2447892000 3600 0 +01}
    {2475108000 0 1 +01}
    {2478736800 3600 0 +01}
    {2505952800 0 1 +01}
    {2508976800 3600 0 +01}
    {2536192800 0 1 +01}
    {2539821600 3600 0 +01}
    {2567037600 0 1 +01}
    {2570666400 3600 0 +01}


    {2597882400 0 1 +01}
    {2600906400 3600 0 +01}
    {2628122400 0 1 +01}
    {2631751200 3600 0 +01}
    {2658967200 0 1 +01}
    {2662596000 3600 0 +01}
    {2689812000 0 1 +01}
    {2692836000 3600 0 +01}
    {2720052000 0 1 +01}
    {2723680800 3600 0 +01}
    {2750896800 0 1 +01}
    {2753920800 3600 0 +01}


    {2781136800 0 1 +01}
    {2784765600 3600 0 +01}
    {2811981600 0 1 +01}
    {2815610400 3600 0 +01}
    {2842826400 0 1 +01}


    {2845850400 3600 0 +01}
    {2873066400 0 1 +01}
    {2876695200 3600 0 +01}
    {2903911200 0 1 +01}
    {2907540000 3600 0 +01}
    {2934756000 0 1 +01}
    {2937780000 3600 0 +01}
    {2964996000 0 1 +01}
    {2968624800 3600 0 +01}
    {2995840800 0 1 +01}
    {2998864800 3600 0 +01}
    {3026080800 0 1 +01}
    {3029709600 3600 0 +01}
    {3056925600 0 1 +01}
    {3060554400 3600 0 +01}
    {3087770400 0 1 +01}
    {3090794400 3600 0 +01}
    {3118010400 0 1 +01}
    {3121639200 3600 0 +01}
    {3148855200 0 1 +01}
    {3152484000 3600 0 +01}




    {3179700000 0 1 +01}
    {3182724000 3600 0 +01}
    {3209940000 0 1 +01}
    {3213568800 3600 0 +01}
    {3240784800 0 1 +01}
    {3243808800 3600 0 +01}
    {3271024800 0 1 +01}
    {3274653600 3600 0 +01}
    {3301869600 0 1 +01}
    {3305498400 3600 0 +01}
    {3332714400 0 1 +01}
    {3335738400 3600 0 +01}
    {3362954400 0 1 +01}
    {3366583200 3600 0 +01}
    {3393799200 0 1 +01}
    {3397428000 3600 0 +01}
    {3424644000 0 1 +01}
    {3427668000 3600 0 +01}
    {3454884000 0 1 +01}
    {3458512800 3600 0 +01}
    {3485728800 0 1 +01}
    {3488752800 3600 0 +01}
    {3515968800 0 1 +01}
    {3519597600 3600 0 +01}
    {3546813600 0 1 +01}
    {3550442400 3600 0 +01}


    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3642372000 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}

}




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
>
>
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
>
|
|
>
>
>
>
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Casablanca) {
    {-9223372036854775808 -1820 0 LMT}
    {-1773012580 0 0 WET}
    {-956361600 3600 1 WEST}
    {-950490000 0 0 WET}
    {-942019200 3600 1 WEST}
    {-761187600 0 0 WET}
    {-617241600 3600 1 WEST}
    {-605149200 0 0 WET}
    {-81432000 3600 1 WEST}
    {-71110800 0 0 WET}
    {141264000 3600 1 WEST}
    {147222000 0 0 WET}
    {199756800 3600 1 WEST}
    {207702000 0 0 WET}
    {231292800 3600 1 WEST}
    {244249200 0 0 WET}
    {265507200 3600 1 WEST}
    {271033200 0 0 WET}
    {448243200 3600 0 CET}
    {504918000 0 0 WET}
    {1212278400 3600 1 WEST}
    {1220223600 0 0 WET}
    {1243814400 3600 1 WEST}
    {1250809200 0 0 WET}
    {1272758400 3600 1 WEST}
    {1281222000 0 0 WET}
    {1301788800 3600 1 WEST}
    {1312066800 0 0 WET}
    {1335664800 3600 1 WEST}
    {1342749600 0 0 WET}
    {1345428000 3600 1 WEST}
    {1348970400 0 0 WET}
    {1367114400 3600 1 WEST}
    {1373162400 0 0 WET}
    {1376100000 3600 1 WEST}
    {1382839200 0 0 WET}
    {1396144800 3600 1 WEST}
    {1403920800 0 0 WET}
    {1406944800 3600 1 WEST}
    {1414288800 0 0 WET}
    {1427594400 3600 1 WEST}
    {1434247200 0 0 WET}
    {1437271200 3600 1 WEST}
    {1445738400 0 0 WET}
    {1459044000 3600 1 WEST}
    {1465092000 0 0 WET}
    {1468116000 3600 1 WEST}
    {1477792800 0 0 WET}
    {1490493600 3600 1 WEST}
    {1495332000 0 0 WET}
    {1498960800 3600 1 WEST}
    {1509242400 0 0 WET}
    {1521943200 3600 1 WEST}
    {1526176800 0 0 WET}
    {1529200800 3600 1 WEST}
    {1540692000 0 0 WET}
    {1553997600 3600 1 WEST}
    {1557021600 0 0 WET}
    {1560045600 3600 1 WEST}
    {1572141600 0 0 WET}
    {1585447200 3600 1 WEST}
    {1587261600 0 0 WET}
    {1590285600 3600 1 WEST}
    {1603591200 0 0 WET}
    {1616896800 3600 1 WEST}
    {1618106400 0 0 WET}
    {1621130400 3600 1 WEST}
    {1635645600 0 0 WET}
    {1651975200 3600 1 WEST}
    {1667095200 0 0 WET}
    {1682215200 3600 1 WEST}
    {1698544800 0 0 WET}
    {1713060000 3600 1 WEST}
    {1729994400 0 0 WET}
    {1743904800 3600 1 WEST}
    {1761444000 0 0 WET}
    {1774749600 3600 1 WEST}
    {1792893600 0 0 WET}
    {1806199200 3600 1 WEST}
    {1824948000 0 0 WET}
    {1837648800 3600 1 WEST}
    {1856397600 0 0 WET}
    {1869098400 3600 1 WEST}
    {1887847200 0 0 WET}
    {1901152800 3600 1 WEST}
    {1919296800 0 0 WET}
    {1932602400 3600 1 WEST}
    {1950746400 0 0 WET}
    {1964052000 3600 1 WEST}
    {1982800800 0 0 WET}
    {1995501600 3600 1 WEST}
    {2014250400 0 0 WET}
    {2026951200 3600 1 WEST}
    {2045700000 0 0 WET}
    {2058400800 3600 1 WEST}
    {2077149600 0 0 WET}
    {2090455200 3600 1 WEST}
    {2107994400 0 0 WET}
    {2108602800 0 0 WET}
    {2121904800 3600 1 WEST}
    {2138234400 0 0 WET}
    {2140052400 0 0 WET}
    {2153354400 3600 1 WEST}
    {2172103200 0 0 WET}
    {2184804000 3600 1 WEST}
    {2203552800 0 0 WET}
    {2216253600 3600 1 WEST}
    {2235002400 0 0 WET}
    {2248308000 3600 1 WEST}
    {2266452000 0 0 WET}
    {2279757600 3600 1 WEST}
    {2297901600 0 0 WET}
    {2311207200 3600 1 WEST}
    {2329351200 0 0 WET}
    {2342656800 3600 1 WEST}
    {2361405600 0 0 WET}
    {2374106400 3600 1 WEST}
    {2392855200 0 0 WET}
    {2405556000 3600 1 WEST}
    {2424304800 0 0 WET}
    {2437610400 3600 1 WEST}
    {2455754400 0 0 WET}
    {2469060000 3600 1 WEST}
    {2487204000 0 0 WET}
    {2500509600 3600 1 WEST}
    {2519258400 0 0 WET}
    {2531959200 3600 1 WEST}
    {2550708000 0 0 WET}
    {2563408800 3600 1 WEST}
    {2582157600 0 0 WET}
    {2595463200 3600 1 WEST}
    {2613607200 0 0 WET}
    {2626912800 3600 1 WEST}
    {2645056800 0 0 WET}
    {2658362400 3600 1 WEST}
    {2676506400 0 0 WET}
    {2689812000 3600 1 WEST}
    {2708560800 0 0 WET}
    {2721261600 3600 1 WEST}
    {2740010400 0 0 WET}
    {2752711200 3600 1 WEST}
    {2771460000 0 0 WET}
    {2784765600 3600 1 WEST}
    {2802909600 0 0 WET}
    {2816215200 3600 1 WEST}
    {2834359200 0 0 WET}
    {2847664800 3600 1 WEST}
    {2866413600 0 0 WET}
    {2879114400 3600 1 WEST}
    {2897863200 0 0 WET}
    {2910564000 3600 1 WEST}
    {2929312800 0 0 WET}
    {2942013600 3600 1 WEST}
    {2960762400 0 0 WET}
    {2974068000 3600 1 WEST}
    {2992212000 0 0 WET}
    {3005517600 3600 1 WEST}
    {3023661600 0 0 WET}
    {3036967200 3600 1 WEST}
    {3055716000 0 0 WET}
    {3068416800 3600 1 WEST}
    {3087165600 0 0 WET}
    {3099866400 3600 1 WEST}
    {3118615200 0 0 WET}
    {3131920800 3600 1 WEST}
    {3150064800 0 0 WET}
    {3163370400 3600 1 WEST}
    {3181514400 0 0 WET}
    {3194820000 3600 1 WEST}
    {3212964000 0 0 WET}
    {3226269600 3600 1 WEST}
    {3245018400 0 0 WET}
    {3257719200 3600 1 WEST}
    {3276468000 0 0 WET}
    {3289168800 3600 1 WEST}
    {3307917600 0 0 WET}
    {3321223200 3600 1 WEST}
    {3339367200 0 0 WET}
    {3352672800 3600 1 WEST}
    {3370816800 0 0 WET}
    {3384122400 3600 1 WEST}
    {3402871200 0 0 WET}
    {3415572000 3600 1 WEST}
    {3434320800 0 0 WET}
    {3447021600 3600 1 WEST}
    {3465770400 0 0 WET}
    {3479076000 3600 1 WEST}
    {3497220000 0 0 WET}
    {3510525600 3600 1 WEST}
    {3528669600 0 0 WET}
    {3541975200 3600 1 WEST}
    {3560119200 0 0 WET}
    {3573424800 3600 1 WEST}
    {3592173600 0 0 WET}
    {3604874400 3600 1 WEST}
    {3623623200 0 0 WET}
    {3636324000 3600 1 WEST}
    {3655072800 0 0 WET}
    {3668378400 3600 1 WEST}
    {3686522400 0 0 WET}
    {3699828000 3600 1 WEST}
    {3717972000 0 0 WET}
    {3731277600 3600 1 WEST}
    {3750026400 0 0 WET}
    {3762727200 3600 1 WEST}
    {3781476000 0 0 WET}
    {3794176800 3600 1 WEST}
    {3812925600 0 0 WET}
    {3825626400 3600 1 WEST}
    {3844375200 0 0 WET}
    {3857680800 3600 1 WEST}
    {3875824800 0 0 WET}
    {3889130400 3600 1 WEST}
    {3907274400 0 0 WET}
    {3920580000 3600 1 WEST}
    {3939328800 0 0 WET}
    {3952029600 3600 1 WEST}
    {3970778400 0 0 WET}
    {3983479200 3600 1 WEST}
    {4002228000 0 0 WET}
    {4015533600 3600 1 WEST}
    {4033677600 0 0 WET}
    {4046983200 3600 1 WEST}
    {4065127200 0 0 WET}
    {4078432800 3600 1 WEST}
    {4096576800 0 0 WET}
}

Changes to library/tzdata/Africa/Ceuta.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    {-1379293200 3600 1 WEST}
    {-1364774400 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333324800 0 0 WET}
    {-1316390400 3600 1 WEST}
    {-1301270400 0 0 WET}
    {-1293840000 0 0 WET}
    {-94694400 0 0 WET}
    {-81432000 3600 1 WEST}
    {-71110800 0 0 WET}
    {141264000 3600 1 WEST}
    {147222000 0 0 WET}
    {199756800 3600 1 WEST}
    {207702000 0 0 WET}
    {231292800 3600 1 WEST}







<







11
12
13
14
15
16
17

18
19
20
21
22
23
24
    {-1379293200 3600 1 WEST}
    {-1364774400 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333324800 0 0 WET}
    {-1316390400 3600 1 WEST}
    {-1301270400 0 0 WET}
    {-1293840000 0 0 WET}

    {-81432000 3600 1 WEST}
    {-71110800 0 0 WET}
    {141264000 3600 1 WEST}
    {147222000 0 0 WET}
    {199756800 3600 1 WEST}
    {207702000 0 0 WET}
    {231292800 3600 1 WEST}

Changes to library/tzdata/Africa/El_Aaiun.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156


157
158
159
160
161
162
163
164
165


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180


181
182
183
184
185
186
187
188
189
190

191
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/El_Aaiun) {
    {-9223372036854775808 -3168 0 LMT}
    {-1136070432 -3600 0 -01}
    {198291600 0 0 +00}
    {199756800 3600 1 +00}
    {207702000 0 0 +00}
    {231292800 3600 1 +00}
    {244249200 0 0 +00}
    {265507200 3600 1 +00}
    {271033200 0 0 +00}
    {1212278400 3600 1 +00}
    {1220223600 0 0 +00}
    {1243814400 3600 1 +00}
    {1250809200 0 0 +00}
    {1272758400 3600 1 +00}
    {1281222000 0 0 +00}
    {1301788800 3600 1 +00}
    {1312066800 0 0 +00}
    {1335664800 3600 1 +00}
    {1342749600 0 0 +00}
    {1345428000 3600 1 +00}
    {1348970400 0 0 +00}
    {1367114400 3600 1 +00}
    {1373162400 0 0 +00}
    {1376100000 3600 1 +00}
    {1382839200 0 0 +00}
    {1396144800 3600 1 +00}
    {1403920800 0 0 +00}
    {1406944800 3600 1 +00}
    {1414288800 0 0 +00}
    {1427594400 3600 1 +00}
    {1434247200 0 0 +00}
    {1437271200 3600 1 +00}
    {1445738400 0 0 +00}
    {1459044000 3600 1 +00}
    {1465092000 0 0 +00}
    {1468116000 3600 1 +00}
    {1477792800 0 0 +00}
    {1490493600 3600 1 +00}
    {1495332000 0 0 +00}
    {1498960800 3600 1 +00}
    {1509242400 0 0 +00}
    {1521943200 3600 1 +00}
    {1526176800 0 0 +00}
    {1529200800 3600 1 +00}

    {1540695600 3600 0 +01}
    {1557021600 0 1 +01}
    {1560045600 3600 0 +01}


    {1587261600 0 1 +01}


    {1590890400 3600 0 +01}
    {1618106400 0 1 +01}
    {1621130400 3600 0 +01}
    {1648346400 0 1 +01}
    {1651975200 3600 0 +01}
    {1679191200 0 1 +01}
    {1682820000 3600 0 +01}
    {1710036000 0 1 +01}
    {1713060000 3600 0 +01}
    {1740276000 0 1 +01}
    {1743904800 3600 0 +01}
    {1771120800 0 1 +01}
    {1774144800 3600 0 +01}
    {1801965600 0 1 +01}


    {1804989600 3600 0 +01}
    {1832205600 0 1 +01}
    {1835834400 3600 0 +01}
    {1863050400 0 1 +01}


    {1866074400 3600 0 +01}




    {1893290400 0 1 +01}
    {1896919200 3600 0 +01}
    {1924135200 0 1 +01}
    {1927764000 3600 0 +01}
    {1954980000 0 1 +01}
    {1958004000 3600 0 +01}
    {1985220000 0 1 +01}
    {1988848800 3600 0 +01}
    {2016064800 0 1 +01}
    {2019088800 3600 0 +01}
    {2046304800 0 1 +01}
    {2049933600 3600 0 +01}
    {2077149600 0 1 +01}
    {2080778400 3600 0 +01}
    {2107994400 0 1 +01}

    {2111018400 3600 0 +01}
    {2138234400 0 1 +01}

    {2141863200 3600 0 +01}
    {2169079200 0 1 +01}




    {2172708000 3600 0 +01}
    {2199924000 0 1 +01}
    {2202948000 3600 0 +01}


    {2230164000 0 1 +01}
    {2233792800 3600 0 +01}


    {2261008800 0 1 +01}
    {2264032800 3600 0 +01}
    {2291248800 0 1 +01}
    {2294877600 3600 0 +01}
    {2322093600 0 1 +01}
    {2325722400 3600 0 +01}
    {2352938400 0 1 +01}
    {2355962400 3600 0 +01}
    {2383178400 0 1 +01}
    {2386807200 3600 0 +01}
    {2414023200 0 1 +01}
    {2417652000 3600 0 +01}
    {2444868000 0 1 +01}
    {2447892000 3600 0 +01}
    {2475108000 0 1 +01}
    {2478736800 3600 0 +01}
    {2505952800 0 1 +01}
    {2508976800 3600 0 +01}
    {2536192800 0 1 +01}
    {2539821600 3600 0 +01}
    {2567037600 0 1 +01}
    {2570666400 3600 0 +01}
    {2597882400 0 1 +01}
    {2600906400 3600 0 +01}




    {2628122400 0 1 +01}
    {2631751200 3600 0 +01}
    {2658967200 0 1 +01}
    {2662596000 3600 0 +01}
    {2689812000 0 1 +01}
    {2692836000 3600 0 +01}
    {2720052000 0 1 +01}
    {2723680800 3600 0 +01}
    {2750896800 0 1 +01}
    {2753920800 3600 0 +01}
    {2781136800 0 1 +01}
    {2784765600 3600 0 +01}
    {2811981600 0 1 +01}
    {2815610400 3600 0 +01}
    {2842826400 0 1 +01}


    {2845850400 3600 0 +01}
    {2873066400 0 1 +01}
    {2876695200 3600 0 +01}
    {2903911200 0 1 +01}
    {2907540000 3600 0 +01}
    {2934756000 0 1 +01}
    {2937780000 3600 0 +01}
    {2964996000 0 1 +01}
    {2968624800 3600 0 +01}
    {2995840800 0 1 +01}
    {2998864800 3600 0 +01}
    {3026080800 0 1 +01}
    {3029709600 3600 0 +01}
    {3056925600 0 1 +01}
    {3060554400 3600 0 +01}
    {3087770400 0 1 +01}
    {3090794400 3600 0 +01}
    {3118010400 0 1 +01}
    {3121639200 3600 0 +01}
    {3148855200 0 1 +01}
    {3152484000 3600 0 +01}
    {3179700000 0 1 +01}
    {3182724000 3600 0 +01}


    {3209940000 0 1 +01}
    {3213568800 3600 0 +01}
    {3240784800 0 1 +01}
    {3243808800 3600 0 +01}
    {3271024800 0 1 +01}
    {3274653600 3600 0 +01}
    {3301869600 0 1 +01}
    {3305498400 3600 0 +01}
    {3332714400 0 1 +01}


    {3335738400 3600 0 +01}
    {3362954400 0 1 +01}
    {3366583200 3600 0 +01}
    {3393799200 0 1 +01}
    {3397428000 3600 0 +01}
    {3424644000 0 1 +01}
    {3427668000 3600 0 +01}
    {3454884000 0 1 +01}
    {3458512800 3600 0 +01}
    {3485728800 0 1 +01}
    {3488752800 3600 0 +01}
    {3515968800 0 1 +01}
    {3519597600 3600 0 +01}
    {3546813600 0 1 +01}
    {3550442400 3600 0 +01}


    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3642372000 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}

}





|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
>
>
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
>
>
|
>
>
>
>
|
|
<
<
|
|
<
<
<
<
<
<
|
|
|
>
|
|
>
|
|
>
>
>
>
|
|
|
>
>
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/El_Aaiun) {
    {-9223372036854775808 -3168 0 LMT}
    {-1136070432 -3600 0 -01}
    {198291600 0 0 WET}
    {199756800 3600 1 WEST}
    {207702000 0 0 WET}
    {231292800 3600 1 WEST}
    {244249200 0 0 WET}
    {265507200 3600 1 WEST}
    {271033200 0 0 WET}
    {1212278400 3600 1 WEST}
    {1220223600 0 0 WET}
    {1243814400 3600 1 WEST}
    {1250809200 0 0 WET}
    {1272758400 3600 1 WEST}
    {1281222000 0 0 WET}
    {1301788800 3600 1 WEST}
    {1312066800 0 0 WET}
    {1335664800 3600 1 WEST}
    {1342749600 0 0 WET}
    {1345428000 3600 1 WEST}
    {1348970400 0 0 WET}
    {1367114400 3600 1 WEST}
    {1373162400 0 0 WET}
    {1376100000 3600 1 WEST}
    {1382839200 0 0 WET}
    {1396144800 3600 1 WEST}
    {1403920800 0 0 WET}
    {1406944800 3600 1 WEST}
    {1414288800 0 0 WET}
    {1427594400 3600 1 WEST}
    {1434247200 0 0 WET}
    {1437271200 3600 1 WEST}
    {1445738400 0 0 WET}
    {1459044000 3600 1 WEST}
    {1465092000 0 0 WET}
    {1468116000 3600 1 WEST}
    {1477792800 0 0 WET}
    {1490493600 3600 1 WEST}
    {1495332000 0 0 WET}
    {1498960800 3600 1 WEST}
    {1509242400 0 0 WET}
    {1521943200 3600 1 WEST}
    {1526176800 0 0 WET}
    {1529200800 3600 1 WEST}
    {1540692000 0 0 WET}
    {1553997600 3600 1 WEST}
    {1557021600 0 0 WET}
    {1560045600 3600 1 WEST}
    {1572141600 0 0 WET}
    {1585447200 3600 1 WEST}
    {1587261600 0 0 WET}
    {1590285600 3600 1 WEST}
    {1603591200 0 0 WET}
    {1616896800 3600 1 WEST}
    {1618106400 0 0 WET}
    {1621130400 3600 1 WEST}
    {1635645600 0 0 WET}
    {1651975200 3600 1 WEST}
    {1667095200 0 0 WET}
    {1682215200 3600 1 WEST}
    {1698544800 0 0 WET}
    {1713060000 3600 1 WEST}
    {1729994400 0 0 WET}
    {1743904800 3600 1 WEST}
    {1761444000 0 0 WET}
    {1774749600 3600 1 WEST}
    {1792893600 0 0 WET}
    {1806199200 3600 1 WEST}
    {1824948000 0 0 WET}
    {1837648800 3600 1 WEST}
    {1856397600 0 0 WET}
    {1869098400 3600 1 WEST}
    {1887847200 0 0 WET}
    {1901152800 3600 1 WEST}
    {1919296800 0 0 WET}
    {1932602400 3600 1 WEST}
    {1950746400 0 0 WET}
    {1964052000 3600 1 WEST}
    {1982800800 0 0 WET}
    {1995501600 3600 1 WEST}
    {2014250400 0 0 WET}
    {2026951200 3600 1 WEST}


    {2045700000 0 0 WET}
    {2058400800 3600 1 WEST}






    {2077149600 0 0 WET}
    {2090455200 3600 1 WEST}
    {2107994400 0 0 WET}
    {2108602800 0 0 WET}
    {2121904800 3600 1 WEST}
    {2138234400 0 0 WET}
    {2140052400 0 0 WET}
    {2153354400 3600 1 WEST}
    {2172103200 0 0 WET}
    {2184804000 3600 1 WEST}
    {2203552800 0 0 WET}
    {2216253600 3600 1 WEST}
    {2235002400 0 0 WET}
    {2248308000 3600 1 WEST}
    {2266452000 0 0 WET}
    {2279757600 3600 1 WEST}
    {2297901600 0 0 WET}
    {2311207200 3600 1 WEST}
    {2329351200 0 0 WET}
    {2342656800 3600 1 WEST}
    {2361405600 0 0 WET}
    {2374106400 3600 1 WEST}
    {2392855200 0 0 WET}
    {2405556000 3600 1 WEST}
    {2424304800 0 0 WET}
    {2437610400 3600 1 WEST}
    {2455754400 0 0 WET}
    {2469060000 3600 1 WEST}
    {2487204000 0 0 WET}
    {2500509600 3600 1 WEST}
    {2519258400 0 0 WET}
    {2531959200 3600 1 WEST}
    {2550708000 0 0 WET}
    {2563408800 3600 1 WEST}
    {2582157600 0 0 WET}
    {2595463200 3600 1 WEST}
    {2613607200 0 0 WET}
    {2626912800 3600 1 WEST}
    {2645056800 0 0 WET}
    {2658362400 3600 1 WEST}
    {2676506400 0 0 WET}
    {2689812000 3600 1 WEST}
    {2708560800 0 0 WET}
    {2721261600 3600 1 WEST}
    {2740010400 0 0 WET}
    {2752711200 3600 1 WEST}
    {2771460000 0 0 WET}
    {2784765600 3600 1 WEST}
    {2802909600 0 0 WET}
    {2816215200 3600 1 WEST}
    {2834359200 0 0 WET}
    {2847664800 3600 1 WEST}
    {2866413600 0 0 WET}
    {2879114400 3600 1 WEST}
    {2897863200 0 0 WET}
    {2910564000 3600 1 WEST}
    {2929312800 0 0 WET}
    {2942013600 3600 1 WEST}
    {2960762400 0 0 WET}
    {2974068000 3600 1 WEST}
    {2992212000 0 0 WET}
    {3005517600 3600 1 WEST}
    {3023661600 0 0 WET}
    {3036967200 3600 1 WEST}
    {3055716000 0 0 WET}
    {3068416800 3600 1 WEST}
    {3087165600 0 0 WET}
    {3099866400 3600 1 WEST}
    {3118615200 0 0 WET}
    {3131920800 3600 1 WEST}
    {3150064800 0 0 WET}
    {3163370400 3600 1 WEST}
    {3181514400 0 0 WET}
    {3194820000 3600 1 WEST}
    {3212964000 0 0 WET}
    {3226269600 3600 1 WEST}
    {3245018400 0 0 WET}
    {3257719200 3600 1 WEST}
    {3276468000 0 0 WET}
    {3289168800 3600 1 WEST}
    {3307917600 0 0 WET}
    {3321223200 3600 1 WEST}
    {3339367200 0 0 WET}
    {3352672800 3600 1 WEST}
    {3370816800 0 0 WET}
    {3384122400 3600 1 WEST}
    {3402871200 0 0 WET}
    {3415572000 3600 1 WEST}
    {3434320800 0 0 WET}
    {3447021600 3600 1 WEST}
    {3465770400 0 0 WET}
    {3479076000 3600 1 WEST}
    {3497220000 0 0 WET}
    {3510525600 3600 1 WEST}
    {3528669600 0 0 WET}
    {3541975200 3600 1 WEST}
    {3560119200 0 0 WET}
    {3573424800 3600 1 WEST}
    {3592173600 0 0 WET}
    {3604874400 3600 1 WEST}
    {3623623200 0 0 WET}
    {3636324000 3600 1 WEST}
    {3655072800 0 0 WET}
    {3668378400 3600 1 WEST}
    {3686522400 0 0 WET}
    {3699828000 3600 1 WEST}
    {3717972000 0 0 WET}
    {3731277600 3600 1 WEST}
    {3750026400 0 0 WET}
    {3762727200 3600 1 WEST}
    {3781476000 0 0 WET}
    {3794176800 3600 1 WEST}
    {3812925600 0 0 WET}
    {3825626400 3600 1 WEST}
    {3844375200 0 0 WET}
    {3857680800 3600 1 WEST}
    {3875824800 0 0 WET}
    {3889130400 3600 1 WEST}
    {3907274400 0 0 WET}
    {3920580000 3600 1 WEST}
    {3939328800 0 0 WET}
    {3952029600 3600 1 WEST}
    {3970778400 0 0 WET}
    {3983479200 3600 1 WEST}
    {4002228000 0 0 WET}
    {4015533600 3600 1 WEST}
    {4033677600 0 0 WET}
    {4046983200 3600 1 WEST}
    {4065127200 0 0 WET}
    {4078432800 3600 1 WEST}
    {4096576800 0 0 WET}
}

Changes to library/tzdata/Africa/Juba.

32
33
34
35
36
37
38
39
40
    {419983200 10800 1 CAST}
    {435013200 7200 0 CAT}
    {452037600 10800 1 CAST}
    {466635600 7200 0 CAT}
    {483487200 10800 1 CAST}
    {498171600 7200 0 CAT}
    {947930400 10800 0 EAT}
    {1612126800 7200 0 CAT}
}







<

32
33
34
35
36
37
38

39
    {419983200 10800 1 CAST}
    {435013200 7200 0 CAT}
    {452037600 10800 1 CAST}
    {466635600 7200 0 CAT}
    {483487200 10800 1 CAST}
    {498171600 7200 0 CAT}
    {947930400 10800 0 EAT}

}

Changes to library/tzdata/Africa/Lagos.

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Lagos) {
    {-9223372036854775808 815 0 LMT}
    {-2035584815 0 0 GMT}
    {-1940889600 815 0 LMT}
    {-1767226415 1800 0 +0030}
    {-1588465800 3600 0 WAT}
}



|
<
<
<
|

1
2
3
4



5
6
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Lagos) {
    {-9223372036854775808 816 0 LMT}



    {-1588464816 3600 0 WAT}
}

Changes to library/tzdata/Africa/Nairobi.

1
2
3
4
5
6
7
8
9
10
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Nairobi) {
    {-9223372036854775808 8836 0 LMT}
    {-1946168836 9000 0 +0230}
    {-1309746600 10800 0 EAT}
    {-1261969200 9000 0 +0230}
    {-1041388200 9900 0 +0245}
    {-865305900 10800 0 EAT}
}




<
|
|
|
|

1
2
3
4

5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Nairobi) {
    {-9223372036854775808 8836 0 LMT}

    {-1309746436 10800 0 EAT}
    {-1262314800 9000 0 +0230}
    {-946780200 9900 0 +0245}
    {-315629100 10800 0 EAT}
}

Changes to library/tzdata/Africa/Sao_Tome.

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Sao_Tome) {
    {-9223372036854775808 1616 0 LMT}
    {-2713912016 -2205 0 LMT}
    {-1830384000 0 0 GMT}
    {1514768400 3600 0 WAT}
    {1546304400 0 0 GMT}
}







<

1
2
3
4
5
6
7

8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Sao_Tome) {
    {-9223372036854775808 1616 0 LMT}
    {-2713912016 -2205 0 LMT}
    {-1830384000 0 0 GMT}
    {1514768400 3600 0 WAT}

}

Changes to library/tzdata/America/Anguilla.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Anguilla) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Anguilla) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Antigua.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Antigua) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Antigua) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Aruba.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Aruba) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Aruba) $TZData(:America/Curacao)

Changes to library/tzdata/America/Atikokan.

1
2
3
4
5









# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Panama)]} {
    LoadTimeZoneFile America/Panama
}
set TZData(:America/Atikokan) $TZData(:America/Panama)










<
<
|
|
>
>
>
>
>
>
>
>
>
1


2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Atikokan) {
    {-9223372036854775808 -21988 0 LMT}
    {-2366733212 -21600 0 CST}
    {-1632067200 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-923248800 -18000 1 CDT}
    {-880214400 -18000 0 CWT}
    {-769395600 -18000 1 CPT}
    {-765388800 -18000 0 EST}
}

Changes to library/tzdata/America/Bahia_Banderas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bahia_Banderas) {
    {-9223372036854775808 -25260 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bahia_Banderas) {
    {-9223372036854775808 -25260 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
61
62
63
64
65
66
67


























































































































































68
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Barbados.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Barbados) {
    {-9223372036854775808 -14309 0 LMT}
    {-1841256091 -14400 0 AST}
    {-874263600 -10800 1 ADT}
    {-862682400 -14400 0 AST}
    {-841604400 -10800 1 ADT}
    {-830714400 -14400 0 AST}
    {-820526400 -14400 0 -0330}
    {-811882800 -12600 1 AST}
    {-798660000 -14400 0 -0330}
    {-788904000 -14400 0 AST}
    {234943200 -10800 1 ADT}
    {244616400 -14400 0 AST}
    {261554400 -10800 1 ADT}
    {276066000 -14400 0 AST}
    {293004000 -10800 1 ADT}
    {307515600 -14400 0 AST}
    {325058400 -10800 1 ADT}




|
<
|
<
<
<
<
<
<







1
2
3
4
5

6






7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Barbados) {
    {-9223372036854775808 -14309 0 LMT}
    {-1451678491 -14309 0 BMT}

    {-1199217691 -14400 0 AST}






    {234943200 -10800 1 ADT}
    {244616400 -14400 0 AST}
    {261554400 -10800 1 ADT}
    {276066000 -14400 0 AST}
    {293004000 -10800 1 ADT}
    {307515600 -14400 0 AST}
    {325058400 -10800 1 ADT}

Changes to library/tzdata/America/Belize.

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
    {-974658600 -21600 0 CST}
    {-954093600 -19800 1 -0530}
    {-943209000 -21600 0 CST}
    {-922644000 -19800 1 -0530}
    {-911759400 -21600 0 CST}
    {-891194400 -19800 1 -0530}
    {-879705000 -21600 0 CST}
    {-868212000 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-758746800 -21600 0 CST}
    {-701892000 -19800 1 -0530}
    {-690402600 -21600 0 CST}
    {-670442400 -19800 1 -0530}
    {-658953000 -21600 0 CST}
    {-638992800 -19800 1 -0530}
    {-627503400 -21600 0 CST}
    {-606938400 -19800 1 -0530}
    {-596053800 -21600 0 CST}
    {-575488800 -19800 1 -0530}
    {-564604200 -21600 0 CST}
    {-544039200 -19800 1 -0530}
    {-532549800 -21600 0 CST}
    {-512589600 -19800 1 -0530}
    {-501100200 -21600 0 CST}
    {-481140000 -19800 1 -0530}
    {-469650600 -21600 0 CST}
    {-449690400 -19800 1 -0530}
    {-438201000 -21600 0 CST}
    {-417636000 -19800 1 -0530}
    {-406751400 -21600 0 CST}
    {-386186400 -19800 1 -0530}
    {-375301800 -21600 0 CST}
    {-354736800 -19800 1 -0530}
    {-343247400 -21600 0 CST}
    {-323287200 -19800 1 -0530}
    {-311797800 -21600 0 CST}
    {-291837600 -19800 1 -0530}
    {-280348200 -21600 0 CST}
    {-259783200 -19800 1 -0530}
    {-248898600 -21600 0 CST}
    {-228333600 -19800 1 -0530}
    {-217449000 -21600 0 CST}
    {-196884000 -19800 1 -0530}
    {-185999400 -21600 0 CST}
    {-165434400 -19800 1 -0530}
    {-153945000 -21600 0 CST}
    {-133984800 -19800 1 -0530}
    {-122495400 -21600 0 CST}
    {-102535200 -19800 1 -0530}
    {-91045800 -21600 0 CST}
    {-70480800 -19800 1 -0530}
    {-59596200 -21600 0 CST}
    {123919200 -18000 1 CDT}
    {129618000 -21600 0 CST}
    {409039200 -18000 1 CDT}
    {413874000 -21600 0 CST}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|





47
48
49
50
51
52
53











































54
55
56
57
58
59
60
    {-974658600 -21600 0 CST}
    {-954093600 -19800 1 -0530}
    {-943209000 -21600 0 CST}
    {-922644000 -19800 1 -0530}
    {-911759400 -21600 0 CST}
    {-891194400 -19800 1 -0530}
    {-879705000 -21600 0 CST}











































    {-859744800 -19800 1 -0530}
    {-848255400 -21600 0 CST}
    {123919200 -18000 1 CDT}
    {129618000 -21600 0 CST}
    {409039200 -18000 1 CDT}
    {413874000 -21600 0 CST}
}

Changes to library/tzdata/America/Blanc-Sablon.

1
2
3
4
5









# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Blanc-Sablon) $TZData(:America/Puerto_Rico)










<
<
|
|
>
>
>
>
>
>
>
>
>
1


2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Blanc-Sablon) {
    {-9223372036854775808 -13708 0 LMT}
    {-2713896692 -14400 0 AST}
    {-1632074400 -10800 1 ADT}
    {-1615143600 -14400 0 AST}
    {-880221600 -10800 1 AWT}
    {-769395600 -10800 1 APT}
    {-765399600 -14400 0 AST}
    {14400 -14400 0 AST}
}

Changes to library/tzdata/America/Bogota.

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bogota) {
    {-9223372036854775808 -17776 0 LMT}
    {-2707671824 -17776 0 BMT}
    {-1739041424 -18000 0 -05}
    {704869200 -14400 1 -05}
    {729057600 -18000 0 -05}
}







|

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bogota) {
    {-9223372036854775808 -17776 0 LMT}
    {-2707671824 -17776 0 BMT}
    {-1739041424 -18000 0 -05}
    {704869200 -14400 1 -05}
    {733896000 -18000 0 -05}
}

Changes to library/tzdata/America/Cambridge_Bay.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cambridge_Bay) {
    {-9223372036854775808 0 0 -00}
    {-1577923200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {136371600 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {167821200 -21600 1 MDT}
    {183542400 -25200 0 MST}
    {199270800 -21600 1 MDT}
    {215596800 -25200 0 MST}
    {230720400 -21600 1 MDT}
    {247046400 -25200 0 MST}
    {262774800 -21600 1 MDT}
    {278496000 -25200 0 MST}
    {294224400 -21600 1 MDT}
    {309945600 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}
    {420022800 -21600 1 MDT}








<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<







1
2
3
4
5
6
7
8




9








10


11
12
13
14
15
16
17
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cambridge_Bay) {
    {-9223372036854775808 0 0 -00}
    {-1577923200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}




    {-147891600 -18000 1 MDDT}








    {-131562000 -25200 0 MST}


    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}
    {420022800 -21600 1 MDT}

Changes to library/tzdata/America/Campo_Grande.

89
90
91
92
93
94
95

































































































































































96
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}

































































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}
    {1572753600 -10800 1 -04}
    {1581822000 -14400 0 -04}
    {1604203200 -10800 1 -04}
    {1613876400 -14400 0 -04}
    {1636257600 -10800 1 -04}
    {1645326000 -14400 0 -04}
    {1667707200 -10800 1 -04}
    {1677380400 -14400 0 -04}
    {1699156800 -10800 1 -04}
    {1708225200 -14400 0 -04}
    {1730606400 -10800 1 -04}
    {1739674800 -14400 0 -04}
    {1762056000 -10800 1 -04}
    {1771729200 -14400 0 -04}
    {1793505600 -10800 1 -04}
    {1803178800 -14400 0 -04}
    {1825560000 -10800 1 -04}
    {1834628400 -14400 0 -04}
    {1857009600 -10800 1 -04}
    {1866078000 -14400 0 -04}
    {1888459200 -10800 1 -04}
    {1897527600 -14400 0 -04}
    {1919908800 -10800 1 -04}
    {1928977200 -14400 0 -04}
    {1951358400 -10800 1 -04}
    {1960426800 -14400 0 -04}
    {1983412800 -10800 1 -04}
    {1992481200 -14400 0 -04}
    {2014862400 -10800 1 -04}
    {2024535600 -14400 0 -04}
    {2046312000 -10800 1 -04}
    {2055380400 -14400 0 -04}
    {2077761600 -10800 1 -04}
    {2086830000 -14400 0 -04}
    {2109211200 -10800 1 -04}
    {2118884400 -14400 0 -04}
    {2140660800 -10800 1 -04}
    {2150334000 -14400 0 -04}
    {2172715200 -10800 1 -04}
    {2181783600 -14400 0 -04}
    {2204164800 -10800 1 -04}
    {2213233200 -14400 0 -04}
    {2235614400 -10800 1 -04}
    {2244682800 -14400 0 -04}
    {2267064000 -10800 1 -04}
    {2276132400 -14400 0 -04}
    {2298513600 -10800 1 -04}
    {2307582000 -14400 0 -04}
    {2329963200 -10800 1 -04}
    {2339636400 -14400 0 -04}
    {2362017600 -10800 1 -04}
    {2371086000 -14400 0 -04}
    {2393467200 -10800 1 -04}
    {2402535600 -14400 0 -04}
    {2424916800 -10800 1 -04}
    {2433985200 -14400 0 -04}
    {2456366400 -10800 1 -04}
    {2465434800 -14400 0 -04}
    {2487816000 -10800 1 -04}
    {2497489200 -14400 0 -04}
    {2519870400 -10800 1 -04}
    {2528938800 -14400 0 -04}
    {2551320000 -10800 1 -04}
    {2560388400 -14400 0 -04}
    {2582769600 -10800 1 -04}
    {2591838000 -14400 0 -04}
    {2614219200 -10800 1 -04}
    {2623287600 -14400 0 -04}
    {2645668800 -10800 1 -04}
    {2654737200 -14400 0 -04}
    {2677118400 -10800 1 -04}
    {2686791600 -14400 0 -04}
    {2709172800 -10800 1 -04}
    {2718241200 -14400 0 -04}
    {2740622400 -10800 1 -04}
    {2749690800 -14400 0 -04}
    {2772072000 -10800 1 -04}
    {2781140400 -14400 0 -04}
    {2803521600 -10800 1 -04}
    {2812590000 -14400 0 -04}
    {2834971200 -10800 1 -04}
    {2844039600 -14400 0 -04}
    {2867025600 -10800 1 -04}
    {2876094000 -14400 0 -04}
    {2898475200 -10800 1 -04}
    {2907543600 -14400 0 -04}
    {2929924800 -10800 1 -04}
    {2938993200 -14400 0 -04}
    {2961374400 -10800 1 -04}
    {2970442800 -14400 0 -04}
    {2992824000 -10800 1 -04}
    {3001892400 -14400 0 -04}
    {3024273600 -10800 1 -04}
    {3033946800 -14400 0 -04}
    {3056328000 -10800 1 -04}
    {3065396400 -14400 0 -04}
    {3087777600 -10800 1 -04}
    {3096846000 -14400 0 -04}
    {3119227200 -10800 1 -04}
    {3128295600 -14400 0 -04}
    {3150676800 -10800 1 -04}
    {3159745200 -14400 0 -04}
    {3182126400 -10800 1 -04}
    {3191194800 -14400 0 -04}
    {3213576000 -10800 1 -04}
    {3223249200 -14400 0 -04}
    {3245630400 -10800 1 -04}
    {3254698800 -14400 0 -04}
    {3277080000 -10800 1 -04}
    {3286148400 -14400 0 -04}
    {3308529600 -10800 1 -04}
    {3317598000 -14400 0 -04}
    {3339979200 -10800 1 -04}
    {3349047600 -14400 0 -04}
    {3371428800 -10800 1 -04}
    {3381102000 -14400 0 -04}
    {3403483200 -10800 1 -04}
    {3412551600 -14400 0 -04}
    {3434932800 -10800 1 -04}
    {3444001200 -14400 0 -04}
    {3466382400 -10800 1 -04}
    {3475450800 -14400 0 -04}
    {3497832000 -10800 1 -04}
    {3506900400 -14400 0 -04}
    {3529281600 -10800 1 -04}
    {3538350000 -14400 0 -04}
    {3560731200 -10800 1 -04}
    {3570404400 -14400 0 -04}
    {3592785600 -10800 1 -04}
    {3601854000 -14400 0 -04}
    {3624235200 -10800 1 -04}
    {3633303600 -14400 0 -04}
    {3655684800 -10800 1 -04}
    {3664753200 -14400 0 -04}
    {3687134400 -10800 1 -04}
    {3696202800 -14400 0 -04}
    {3718584000 -10800 1 -04}
    {3727652400 -14400 0 -04}
    {3750638400 -10800 1 -04}
    {3759706800 -14400 0 -04}
    {3782088000 -10800 1 -04}
    {3791156400 -14400 0 -04}
    {3813537600 -10800 1 -04}
    {3822606000 -14400 0 -04}
    {3844987200 -10800 1 -04}
    {3854055600 -14400 0 -04}
    {3876436800 -10800 1 -04}
    {3885505200 -14400 0 -04}
    {3907886400 -10800 1 -04}
    {3917559600 -14400 0 -04}
    {3939940800 -10800 1 -04}
    {3949009200 -14400 0 -04}
    {3971390400 -10800 1 -04}
    {3980458800 -14400 0 -04}
    {4002840000 -10800 1 -04}
    {4011908400 -14400 0 -04}
    {4034289600 -10800 1 -04}
    {4043358000 -14400 0 -04}
    {4065739200 -10800 1 -04}
    {4074807600 -14400 0 -04}
    {4097188800 -10800 1 -04}
}

Changes to library/tzdata/America/Chihuahua.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Chihuahua) {
    {-9223372036854775808 -25460 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Chihuahua) {
    {-9223372036854775808 -25460 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
59
60
61
62
63
64
65



66























































































































































67
    {1554627600 -21600 1 MDT}
    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}



    {1667120400 -21600 0 CST}























































































































































}







>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
    {1554627600 -21600 1 MDT}
    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}
    {1667116800 -25200 0 MST}
    {1680426000 -21600 1 MDT}
    {1698566400 -25200 0 MST}
    {1712480400 -21600 1 MDT}
    {1730016000 -25200 0 MST}
    {1743930000 -21600 1 MDT}
    {1761465600 -25200 0 MST}
    {1775379600 -21600 1 MDT}
    {1792915200 -25200 0 MST}
    {1806829200 -21600 1 MDT}
    {1824969600 -25200 0 MST}
    {1838278800 -21600 1 MDT}
    {1856419200 -25200 0 MST}
    {1869728400 -21600 1 MDT}
    {1887868800 -25200 0 MST}
    {1901782800 -21600 1 MDT}
    {1919318400 -25200 0 MST}
    {1933232400 -21600 1 MDT}
    {1950768000 -25200 0 MST}
    {1964682000 -21600 1 MDT}
    {1982822400 -25200 0 MST}
    {1996131600 -21600 1 MDT}
    {2014272000 -25200 0 MST}
    {2027581200 -21600 1 MDT}
    {2045721600 -25200 0 MST}
    {2059030800 -21600 1 MDT}
    {2077171200 -25200 0 MST}
    {2091085200 -21600 1 MDT}
    {2108620800 -25200 0 MST}
    {2122534800 -21600 1 MDT}
    {2140070400 -25200 0 MST}
    {2153984400 -21600 1 MDT}
    {2172124800 -25200 0 MST}
    {2185434000 -21600 1 MDT}
    {2203574400 -25200 0 MST}
    {2216883600 -21600 1 MDT}
    {2235024000 -25200 0 MST}
    {2248938000 -21600 1 MDT}
    {2266473600 -25200 0 MST}
    {2280387600 -21600 1 MDT}
    {2297923200 -25200 0 MST}
    {2311837200 -21600 1 MDT}
    {2329372800 -25200 0 MST}
    {2343286800 -21600 1 MDT}
    {2361427200 -25200 0 MST}
    {2374736400 -21600 1 MDT}
    {2392876800 -25200 0 MST}
    {2406186000 -21600 1 MDT}
    {2424326400 -25200 0 MST}
    {2438240400 -21600 1 MDT}
    {2455776000 -25200 0 MST}
    {2469690000 -21600 1 MDT}
    {2487225600 -25200 0 MST}
    {2501139600 -21600 1 MDT}
    {2519280000 -25200 0 MST}
    {2532589200 -21600 1 MDT}
    {2550729600 -25200 0 MST}
    {2564038800 -21600 1 MDT}
    {2582179200 -25200 0 MST}
    {2596093200 -21600 1 MDT}
    {2613628800 -25200 0 MST}
    {2627542800 -21600 1 MDT}
    {2645078400 -25200 0 MST}
    {2658992400 -21600 1 MDT}
    {2676528000 -25200 0 MST}
    {2690442000 -21600 1 MDT}
    {2708582400 -25200 0 MST}
    {2721891600 -21600 1 MDT}
    {2740032000 -25200 0 MST}
    {2753341200 -21600 1 MDT}
    {2771481600 -25200 0 MST}
    {2785395600 -21600 1 MDT}
    {2802931200 -25200 0 MST}
    {2816845200 -21600 1 MDT}
    {2834380800 -25200 0 MST}
    {2848294800 -21600 1 MDT}
    {2866435200 -25200 0 MST}
    {2879744400 -21600 1 MDT}
    {2897884800 -25200 0 MST}
    {2911194000 -21600 1 MDT}
    {2929334400 -25200 0 MST}
    {2942643600 -21600 1 MDT}
    {2960784000 -25200 0 MST}
    {2974698000 -21600 1 MDT}
    {2992233600 -25200 0 MST}
    {3006147600 -21600 1 MDT}
    {3023683200 -25200 0 MST}
    {3037597200 -21600 1 MDT}
    {3055737600 -25200 0 MST}
    {3069046800 -21600 1 MDT}
    {3087187200 -25200 0 MST}
    {3100496400 -21600 1 MDT}
    {3118636800 -25200 0 MST}
    {3132550800 -21600 1 MDT}
    {3150086400 -25200 0 MST}
    {3164000400 -21600 1 MDT}
    {3181536000 -25200 0 MST}
    {3195450000 -21600 1 MDT}
    {3212985600 -25200 0 MST}
    {3226899600 -21600 1 MDT}
    {3245040000 -25200 0 MST}
    {3258349200 -21600 1 MDT}
    {3276489600 -25200 0 MST}
    {3289798800 -21600 1 MDT}
    {3307939200 -25200 0 MST}
    {3321853200 -21600 1 MDT}
    {3339388800 -25200 0 MST}
    {3353302800 -21600 1 MDT}
    {3370838400 -25200 0 MST}
    {3384752400 -21600 1 MDT}
    {3402892800 -25200 0 MST}
    {3416202000 -21600 1 MDT}
    {3434342400 -25200 0 MST}
    {3447651600 -21600 1 MDT}
    {3465792000 -25200 0 MST}
    {3479706000 -21600 1 MDT}
    {3497241600 -25200 0 MST}
    {3511155600 -21600 1 MDT}
    {3528691200 -25200 0 MST}
    {3542605200 -21600 1 MDT}
    {3560140800 -25200 0 MST}
    {3574054800 -21600 1 MDT}
    {3592195200 -25200 0 MST}
    {3605504400 -21600 1 MDT}
    {3623644800 -25200 0 MST}
    {3636954000 -21600 1 MDT}
    {3655094400 -25200 0 MST}
    {3669008400 -21600 1 MDT}
    {3686544000 -25200 0 MST}
    {3700458000 -21600 1 MDT}
    {3717993600 -25200 0 MST}
    {3731907600 -21600 1 MDT}
    {3750048000 -25200 0 MST}
    {3763357200 -21600 1 MDT}
    {3781497600 -25200 0 MST}
    {3794806800 -21600 1 MDT}
    {3812947200 -25200 0 MST}
    {3826256400 -21600 1 MDT}
    {3844396800 -25200 0 MST}
    {3858310800 -21600 1 MDT}
    {3875846400 -25200 0 MST}
    {3889760400 -21600 1 MDT}
    {3907296000 -25200 0 MST}
    {3921210000 -21600 1 MDT}
    {3939350400 -25200 0 MST}
    {3952659600 -21600 1 MDT}
    {3970800000 -25200 0 MST}
    {3984109200 -21600 1 MDT}
    {4002249600 -25200 0 MST}
    {4016163600 -21600 1 MDT}
    {4033699200 -25200 0 MST}
    {4047613200 -21600 1 MDT}
    {4065148800 -25200 0 MST}
    {4079062800 -21600 1 MDT}
    {4096598400 -25200 0 MST}
}

Changes to library/tzdata/America/Coral_Harbour.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Panama)]} {
    LoadTimeZoneFile America/Panama
}
set TZData(:America/Coral_Harbour) $TZData(:America/Panama)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Atikokan)]} {
    LoadTimeZoneFile America/Atikokan
}
set TZData(:America/Coral_Harbour) $TZData(:America/Atikokan)

Changes to library/tzdata/America/Creston.

1
2
3
4
5





# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Phoenix)]} {
    LoadTimeZoneFile America/Phoenix
}
set TZData(:America/Creston) $TZData(:America/Phoenix)






<
<
|
|
>
>
>
>
>
1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Creston) {
    {-9223372036854775808 -27964 0 LMT}
    {-2713882436 -25200 0 MST}
    {-1680454800 -28800 0 PST}
    {-1627833600 -25200 0 MST}
}

Changes to library/tzdata/America/Cuiaba.

89
90
91
92
93
94
95

































































































































































96
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}

































































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}
    {1572753600 -10800 1 -04}
    {1581822000 -14400 0 -04}
    {1604203200 -10800 1 -04}
    {1613876400 -14400 0 -04}
    {1636257600 -10800 1 -04}
    {1645326000 -14400 0 -04}
    {1667707200 -10800 1 -04}
    {1677380400 -14400 0 -04}
    {1699156800 -10800 1 -04}
    {1708225200 -14400 0 -04}
    {1730606400 -10800 1 -04}
    {1739674800 -14400 0 -04}
    {1762056000 -10800 1 -04}
    {1771729200 -14400 0 -04}
    {1793505600 -10800 1 -04}
    {1803178800 -14400 0 -04}
    {1825560000 -10800 1 -04}
    {1834628400 -14400 0 -04}
    {1857009600 -10800 1 -04}
    {1866078000 -14400 0 -04}
    {1888459200 -10800 1 -04}
    {1897527600 -14400 0 -04}
    {1919908800 -10800 1 -04}
    {1928977200 -14400 0 -04}
    {1951358400 -10800 1 -04}
    {1960426800 -14400 0 -04}
    {1983412800 -10800 1 -04}
    {1992481200 -14400 0 -04}
    {2014862400 -10800 1 -04}
    {2024535600 -14400 0 -04}
    {2046312000 -10800 1 -04}
    {2055380400 -14400 0 -04}
    {2077761600 -10800 1 -04}
    {2086830000 -14400 0 -04}
    {2109211200 -10800 1 -04}
    {2118884400 -14400 0 -04}
    {2140660800 -10800 1 -04}
    {2150334000 -14400 0 -04}
    {2172715200 -10800 1 -04}
    {2181783600 -14400 0 -04}
    {2204164800 -10800 1 -04}
    {2213233200 -14400 0 -04}
    {2235614400 -10800 1 -04}
    {2244682800 -14400 0 -04}
    {2267064000 -10800 1 -04}
    {2276132400 -14400 0 -04}
    {2298513600 -10800 1 -04}
    {2307582000 -14400 0 -04}
    {2329963200 -10800 1 -04}
    {2339636400 -14400 0 -04}
    {2362017600 -10800 1 -04}
    {2371086000 -14400 0 -04}
    {2393467200 -10800 1 -04}
    {2402535600 -14400 0 -04}
    {2424916800 -10800 1 -04}
    {2433985200 -14400 0 -04}
    {2456366400 -10800 1 -04}
    {2465434800 -14400 0 -04}
    {2487816000 -10800 1 -04}
    {2497489200 -14400 0 -04}
    {2519870400 -10800 1 -04}
    {2528938800 -14400 0 -04}
    {2551320000 -10800 1 -04}
    {2560388400 -14400 0 -04}
    {2582769600 -10800 1 -04}
    {2591838000 -14400 0 -04}
    {2614219200 -10800 1 -04}
    {2623287600 -14400 0 -04}
    {2645668800 -10800 1 -04}
    {2654737200 -14400 0 -04}
    {2677118400 -10800 1 -04}
    {2686791600 -14400 0 -04}
    {2709172800 -10800 1 -04}
    {2718241200 -14400 0 -04}
    {2740622400 -10800 1 -04}
    {2749690800 -14400 0 -04}
    {2772072000 -10800 1 -04}
    {2781140400 -14400 0 -04}
    {2803521600 -10800 1 -04}
    {2812590000 -14400 0 -04}
    {2834971200 -10800 1 -04}
    {2844039600 -14400 0 -04}
    {2867025600 -10800 1 -04}
    {2876094000 -14400 0 -04}
    {2898475200 -10800 1 -04}
    {2907543600 -14400 0 -04}
    {2929924800 -10800 1 -04}
    {2938993200 -14400 0 -04}
    {2961374400 -10800 1 -04}
    {2970442800 -14400 0 -04}
    {2992824000 -10800 1 -04}
    {3001892400 -14400 0 -04}
    {3024273600 -10800 1 -04}
    {3033946800 -14400 0 -04}
    {3056328000 -10800 1 -04}
    {3065396400 -14400 0 -04}
    {3087777600 -10800 1 -04}
    {3096846000 -14400 0 -04}
    {3119227200 -10800 1 -04}
    {3128295600 -14400 0 -04}
    {3150676800 -10800 1 -04}
    {3159745200 -14400 0 -04}
    {3182126400 -10800 1 -04}
    {3191194800 -14400 0 -04}
    {3213576000 -10800 1 -04}
    {3223249200 -14400 0 -04}
    {3245630400 -10800 1 -04}
    {3254698800 -14400 0 -04}
    {3277080000 -10800 1 -04}
    {3286148400 -14400 0 -04}
    {3308529600 -10800 1 -04}
    {3317598000 -14400 0 -04}
    {3339979200 -10800 1 -04}
    {3349047600 -14400 0 -04}
    {3371428800 -10800 1 -04}
    {3381102000 -14400 0 -04}
    {3403483200 -10800 1 -04}
    {3412551600 -14400 0 -04}
    {3434932800 -10800 1 -04}
    {3444001200 -14400 0 -04}
    {3466382400 -10800 1 -04}
    {3475450800 -14400 0 -04}
    {3497832000 -10800 1 -04}
    {3506900400 -14400 0 -04}
    {3529281600 -10800 1 -04}
    {3538350000 -14400 0 -04}
    {3560731200 -10800 1 -04}
    {3570404400 -14400 0 -04}
    {3592785600 -10800 1 -04}
    {3601854000 -14400 0 -04}
    {3624235200 -10800 1 -04}
    {3633303600 -14400 0 -04}
    {3655684800 -10800 1 -04}
    {3664753200 -14400 0 -04}
    {3687134400 -10800 1 -04}
    {3696202800 -14400 0 -04}
    {3718584000 -10800 1 -04}
    {3727652400 -14400 0 -04}
    {3750638400 -10800 1 -04}
    {3759706800 -14400 0 -04}
    {3782088000 -10800 1 -04}
    {3791156400 -14400 0 -04}
    {3813537600 -10800 1 -04}
    {3822606000 -14400 0 -04}
    {3844987200 -10800 1 -04}
    {3854055600 -14400 0 -04}
    {3876436800 -10800 1 -04}
    {3885505200 -14400 0 -04}
    {3907886400 -10800 1 -04}
    {3917559600 -14400 0 -04}
    {3939940800 -10800 1 -04}
    {3949009200 -14400 0 -04}
    {3971390400 -10800 1 -04}
    {3980458800 -14400 0 -04}
    {4002840000 -10800 1 -04}
    {4011908400 -14400 0 -04}
    {4034289600 -10800 1 -04}
    {4043358000 -14400 0 -04}
    {4065739200 -10800 1 -04}
    {4074807600 -14400 0 -04}
    {4097188800 -10800 1 -04}
}

Changes to library/tzdata/America/Curacao.

1
2
3
4
5




# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Curacao) $TZData(:America/Puerto_Rico)





<
<
|
|
>
>
>
>
1


2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Curacao) {
    {-9223372036854775808 -16547 0 LMT}
    {-1826738653 -16200 0 -0430}
    {-157750200 -14400 0 AST}
}

Changes to library/tzdata/America/Dawson.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Dawson) {
    {-9223372036854775808 -33460 0 LMT}
    {-2188996940 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}
    {-157734000 -32400 0 YST}
    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}
    {120646800 -28800 0 PST}
    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}












<


<







1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Dawson) {
    {-9223372036854775808 -33460 0 LMT}
    {-2188996940 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}

    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}

    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}
92
93
94
95
96
97
98













































































































99

















































100
    {1489312800 -25200 1 PDT}
    {1509872400 -28800 0 PST}
    {1520762400 -25200 1 PDT}
    {1541322000 -28800 0 PST}
    {1552212000 -25200 1 PDT}
    {1572771600 -28800 0 PST}
    {1583661600 -25200 1 PDT}













































































































    {1604217600 -25200 0 MST}

















































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    {1489312800 -25200 1 PDT}
    {1509872400 -28800 0 PST}
    {1520762400 -25200 1 PDT}
    {1541322000 -28800 0 PST}
    {1552212000 -25200 1 PDT}
    {1572771600 -28800 0 PST}
    {1583661600 -25200 1 PDT}
    {1604221200 -28800 0 PST}
    {1615716000 -25200 1 PDT}
    {1636275600 -28800 0 PST}
    {1647165600 -25200 1 PDT}
    {1667725200 -28800 0 PST}
    {1678615200 -25200 1 PDT}
    {1699174800 -28800 0 PST}
    {1710064800 -25200 1 PDT}
    {1730624400 -28800 0 PST}
    {1741514400 -25200 1 PDT}
    {1762074000 -28800 0 PST}
    {1772964000 -25200 1 PDT}
    {1793523600 -28800 0 PST}
    {1805018400 -25200 1 PDT}
    {1825578000 -28800 0 PST}
    {1836468000 -25200 1 PDT}
    {1857027600 -28800 0 PST}
    {1867917600 -25200 1 PDT}
    {1888477200 -28800 0 PST}
    {1899367200 -25200 1 PDT}
    {1919926800 -28800 0 PST}
    {1930816800 -25200 1 PDT}
    {1951376400 -28800 0 PST}
    {1962871200 -25200 1 PDT}
    {1983430800 -28800 0 PST}
    {1994320800 -25200 1 PDT}
    {2014880400 -28800 0 PST}
    {2025770400 -25200 1 PDT}
    {2046330000 -28800 0 PST}
    {2057220000 -25200 1 PDT}
    {2077779600 -28800 0 PST}
    {2088669600 -25200 1 PDT}
    {2109229200 -28800 0 PST}
    {2120119200 -25200 1 PDT}
    {2140678800 -28800 0 PST}
    {2152173600 -25200 1 PDT}
    {2172733200 -28800 0 PST}
    {2183623200 -25200 1 PDT}
    {2204182800 -28800 0 PST}
    {2215072800 -25200 1 PDT}
    {2235632400 -28800 0 PST}
    {2246522400 -25200 1 PDT}
    {2267082000 -28800 0 PST}
    {2277972000 -25200 1 PDT}
    {2298531600 -28800 0 PST}
    {2309421600 -25200 1 PDT}
    {2329981200 -28800 0 PST}
    {2341476000 -25200 1 PDT}
    {2362035600 -28800 0 PST}
    {2372925600 -25200 1 PDT}
    {2393485200 -28800 0 PST}
    {2404375200 -25200 1 PDT}
    {2424934800 -28800 0 PST}
    {2435824800 -25200 1 PDT}
    {2456384400 -28800 0 PST}
    {2467274400 -25200 1 PDT}
    {2487834000 -28800 0 PST}
    {2499328800 -25200 1 PDT}
    {2519888400 -28800 0 PST}
    {2530778400 -25200 1 PDT}
    {2551338000 -28800 0 PST}
    {2562228000 -25200 1 PDT}
    {2582787600 -28800 0 PST}
    {2593677600 -25200 1 PDT}
    {2614237200 -28800 0 PST}
    {2625127200 -25200 1 PDT}
    {2645686800 -28800 0 PST}
    {2656576800 -25200 1 PDT}
    {2677136400 -28800 0 PST}
    {2688631200 -25200 1 PDT}
    {2709190800 -28800 0 PST}
    {2720080800 -25200 1 PDT}
    {2740640400 -28800 0 PST}
    {2751530400 -25200 1 PDT}
    {2772090000 -28800 0 PST}
    {2782980000 -25200 1 PDT}
    {2803539600 -28800 0 PST}
    {2814429600 -25200 1 PDT}
    {2834989200 -28800 0 PST}
    {2846484000 -25200 1 PDT}
    {2867043600 -28800 0 PST}
    {2877933600 -25200 1 PDT}
    {2898493200 -28800 0 PST}
    {2909383200 -25200 1 PDT}
    {2929942800 -28800 0 PST}
    {2940832800 -25200 1 PDT}
    {2961392400 -28800 0 PST}
    {2972282400 -25200 1 PDT}
    {2992842000 -28800 0 PST}
    {3003732000 -25200 1 PDT}
    {3024291600 -28800 0 PST}
    {3035786400 -25200 1 PDT}
    {3056346000 -28800 0 PST}
    {3067236000 -25200 1 PDT}
    {3087795600 -28800 0 PST}
    {3098685600 -25200 1 PDT}
    {3119245200 -28800 0 PST}
    {3130135200 -25200 1 PDT}
    {3150694800 -28800 0 PST}
    {3161584800 -25200 1 PDT}
    {3182144400 -28800 0 PST}
    {3193034400 -25200 1 PDT}
    {3213594000 -28800 0 PST}
    {3225088800 -25200 1 PDT}
    {3245648400 -28800 0 PST}
    {3256538400 -25200 1 PDT}
    {3277098000 -28800 0 PST}
    {3287988000 -25200 1 PDT}
    {3308547600 -28800 0 PST}
    {3319437600 -25200 1 PDT}
    {3339997200 -28800 0 PST}
    {3350887200 -25200 1 PDT}
    {3371446800 -28800 0 PST}
    {3382941600 -25200 1 PDT}
    {3403501200 -28800 0 PST}
    {3414391200 -25200 1 PDT}
    {3434950800 -28800 0 PST}
    {3445840800 -25200 1 PDT}
    {3466400400 -28800 0 PST}
    {3477290400 -25200 1 PDT}
    {3497850000 -28800 0 PST}
    {3508740000 -25200 1 PDT}
    {3529299600 -28800 0 PST}
    {3540189600 -25200 1 PDT}
    {3560749200 -28800 0 PST}
    {3572244000 -25200 1 PDT}
    {3592803600 -28800 0 PST}
    {3603693600 -25200 1 PDT}
    {3624253200 -28800 0 PST}
    {3635143200 -25200 1 PDT}
    {3655702800 -28800 0 PST}
    {3666592800 -25200 1 PDT}
    {3687152400 -28800 0 PST}
    {3698042400 -25200 1 PDT}
    {3718602000 -28800 0 PST}
    {3730096800 -25200 1 PDT}
    {3750656400 -28800 0 PST}
    {3761546400 -25200 1 PDT}
    {3782106000 -28800 0 PST}
    {3792996000 -25200 1 PDT}
    {3813555600 -28800 0 PST}
    {3824445600 -25200 1 PDT}
    {3845005200 -28800 0 PST}
    {3855895200 -25200 1 PDT}
    {3876454800 -28800 0 PST}
    {3887344800 -25200 1 PDT}
    {3907904400 -28800 0 PST}
    {3919399200 -25200 1 PDT}
    {3939958800 -28800 0 PST}
    {3950848800 -25200 1 PDT}
    {3971408400 -28800 0 PST}
    {3982298400 -25200 1 PDT}
    {4002858000 -28800 0 PST}
    {4013748000 -25200 1 PDT}
    {4034307600 -28800 0 PST}
    {4045197600 -25200 1 PDT}
    {4065757200 -28800 0 PST}
    {4076647200 -25200 1 PDT}
    {4097206800 -28800 0 PST}
}

Changes to library/tzdata/America/Detroit.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Detroit) {
    {-9223372036854775808 -19931 0 LMT}
    {-2051202469 -21600 0 CST}
    {-1724083200 -18000 0 EST}
    {-883594800 -18000 0 EST}
    {-880218000 -14400 1 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {-757364400 -18000 0 EST}
    {-684349200 -14400 1 EDT}
    {-671047200 -18000 0 EST}
    {-80506740 -14400 0 EDT}
    {-68666400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-31518000 -18000 0 EST}
    {94712400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {126687600 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {157784400 -18000 0 EST}
    {167814000 -14400 0 EDT}













<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13





14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Detroit) {
    {-9223372036854775808 -19931 0 LMT}
    {-2051202469 -21600 0 CST}
    {-1724083200 -18000 0 EST}
    {-883594800 -18000 0 EST}
    {-880218000 -14400 1 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {-757364400 -18000 0 EST}
    {-684349200 -14400 1 EDT}
    {-671047200 -18000 0 EST}





    {94712400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {126687600 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {157784400 -18000 0 EST}
    {167814000 -14400 0 EDT}

Changes to library/tzdata/America/Dominica.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Dominica) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Dominica) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Edmonton.

16
17
18
19
20
21
22




23
24
25
26
27
28
29
    {-1473001200 -21600 1 MDT}
    {-1459699200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {-715791600 -21600 1 MDT}
    {-702489600 -25200 0 MST}




    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {136371600 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {167821200 -21600 1 MDT}







>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    {-1473001200 -21600 1 MDT}
    {-1459699200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {-715791600 -21600 1 MDT}
    {-702489600 -25200 0 MST}
    {-84380400 -21600 1 MDT}
    {-68659200 -25200 0 MST}
    {-21481200 -21600 1 MDT}
    {-5760000 -25200 0 MST}
    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {136371600 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {167821200 -21600 1 MDT}

Changes to library/tzdata/America/Godthab.

1
2
3
4
5



















































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Nuuk)]} {
    LoadTimeZoneFile America/Nuuk
}
set TZData(:America/Godthab) $TZData(:America/Nuuk)




















































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Godthab) {
    {-9223372036854775808 -12416 0 LMT}
    {-1686083584 -10800 0 -03}
    {323845200 -7200 0 -02}
    {338950800 -10800 0 -03}
    {354675600 -7200 1 -02}
    {370400400 -10800 0 -03}
    {386125200 -7200 1 -02}
    {401850000 -10800 0 -03}
    {417574800 -7200 1 -02}
    {433299600 -10800 0 -03}
    {449024400 -7200 1 -02}
    {465354000 -10800 0 -03}
    {481078800 -7200 1 -02}
    {496803600 -10800 0 -03}
    {512528400 -7200 1 -02}
    {528253200 -10800 0 -03}
    {543978000 -7200 1 -02}
    {559702800 -10800 0 -03}
    {575427600 -7200 1 -02}
    {591152400 -10800 0 -03}
    {606877200 -7200 1 -02}
    {622602000 -10800 0 -03}
    {638326800 -7200 1 -02}
    {654656400 -10800 0 -03}
    {670381200 -7200 1 -02}
    {686106000 -10800 0 -03}
    {701830800 -7200 1 -02}
    {717555600 -10800 0 -03}
    {733280400 -7200 1 -02}
    {749005200 -10800 0 -03}
    {764730000 -7200 1 -02}
    {780454800 -10800 0 -03}
    {796179600 -7200 1 -02}
    {811904400 -10800 0 -03}
    {828234000 -7200 1 -02}
    {846378000 -10800 0 -03}
    {859683600 -7200 1 -02}
    {877827600 -10800 0 -03}
    {891133200 -7200 1 -02}
    {909277200 -10800 0 -03}
    {922582800 -7200 1 -02}
    {941331600 -10800 0 -03}
    {954032400 -7200 1 -02}
    {972781200 -10800 0 -03}
    {985482000 -7200 1 -02}
    {1004230800 -10800 0 -03}
    {1017536400 -7200 1 -02}
    {1035680400 -10800 0 -03}
    {1048986000 -7200 1 -02}
    {1067130000 -10800 0 -03}
    {1080435600 -7200 1 -02}
    {1099184400 -10800 0 -03}
    {1111885200 -7200 1 -02}
    {1130634000 -10800 0 -03}
    {1143334800 -7200 1 -02}
    {1162083600 -10800 0 -03}
    {1174784400 -7200 1 -02}
    {1193533200 -10800 0 -03}
    {1206838800 -7200 1 -02}
    {1224982800 -10800 0 -03}
    {1238288400 -7200 1 -02}
    {1256432400 -10800 0 -03}
    {1269738000 -7200 1 -02}
    {1288486800 -10800 0 -03}
    {1301187600 -7200 1 -02}
    {1319936400 -10800 0 -03}
    {1332637200 -7200 1 -02}
    {1351386000 -10800 0 -03}
    {1364691600 -7200 1 -02}
    {1382835600 -10800 0 -03}
    {1396141200 -7200 1 -02}
    {1414285200 -10800 0 -03}
    {1427590800 -7200 1 -02}
    {1445734800 -10800 0 -03}
    {1459040400 -7200 1 -02}
    {1477789200 -10800 0 -03}
    {1490490000 -7200 1 -02}
    {1509238800 -10800 0 -03}
    {1521939600 -7200 1 -02}
    {1540688400 -10800 0 -03}
    {1553994000 -7200 1 -02}
    {1572138000 -10800 0 -03}
    {1585443600 -7200 1 -02}
    {1603587600 -10800 0 -03}
    {1616893200 -7200 1 -02}
    {1635642000 -10800 0 -03}
    {1648342800 -7200 1 -02}
    {1667091600 -10800 0 -03}
    {1679792400 -7200 1 -02}
    {1698541200 -10800 0 -03}
    {1711846800 -7200 1 -02}
    {1729990800 -10800 0 -03}
    {1743296400 -7200 1 -02}
    {1761440400 -10800 0 -03}
    {1774746000 -7200 1 -02}
    {1792890000 -10800 0 -03}
    {1806195600 -7200 1 -02}
    {1824944400 -10800 0 -03}
    {1837645200 -7200 1 -02}
    {1856394000 -10800 0 -03}
    {1869094800 -7200 1 -02}
    {1887843600 -10800 0 -03}
    {1901149200 -7200 1 -02}
    {1919293200 -10800 0 -03}
    {1932598800 -7200 1 -02}
    {1950742800 -10800 0 -03}
    {1964048400 -7200 1 -02}
    {1982797200 -10800 0 -03}
    {1995498000 -7200 1 -02}
    {2014246800 -10800 0 -03}
    {2026947600 -7200 1 -02}
    {2045696400 -10800 0 -03}
    {2058397200 -7200 1 -02}
    {2077146000 -10800 0 -03}
    {2090451600 -7200 1 -02}
    {2108595600 -10800 0 -03}
    {2121901200 -7200 1 -02}
    {2140045200 -10800 0 -03}
    {2153350800 -7200 1 -02}
    {2172099600 -10800 0 -03}
    {2184800400 -7200 1 -02}
    {2203549200 -10800 0 -03}
    {2216250000 -7200 1 -02}
    {2234998800 -10800 0 -03}
    {2248304400 -7200 1 -02}
    {2266448400 -10800 0 -03}
    {2279754000 -7200 1 -02}
    {2297898000 -10800 0 -03}
    {2311203600 -7200 1 -02}
    {2329347600 -10800 0 -03}
    {2342653200 -7200 1 -02}
    {2361402000 -10800 0 -03}
    {2374102800 -7200 1 -02}
    {2392851600 -10800 0 -03}
    {2405552400 -7200 1 -02}
    {2424301200 -10800 0 -03}
    {2437606800 -7200 1 -02}
    {2455750800 -10800 0 -03}
    {2469056400 -7200 1 -02}
    {2487200400 -10800 0 -03}
    {2500506000 -7200 1 -02}
    {2519254800 -10800 0 -03}
    {2531955600 -7200 1 -02}
    {2550704400 -10800 0 -03}
    {2563405200 -7200 1 -02}
    {2582154000 -10800 0 -03}
    {2595459600 -7200 1 -02}
    {2613603600 -10800 0 -03}
    {2626909200 -7200 1 -02}
    {2645053200 -10800 0 -03}
    {2658358800 -7200 1 -02}
    {2676502800 -10800 0 -03}
    {2689808400 -7200 1 -02}
    {2708557200 -10800 0 -03}
    {2721258000 -7200 1 -02}
    {2740006800 -10800 0 -03}
    {2752707600 -7200 1 -02}
    {2771456400 -10800 0 -03}
    {2784762000 -7200 1 -02}
    {2802906000 -10800 0 -03}
    {2816211600 -7200 1 -02}
    {2834355600 -10800 0 -03}
    {2847661200 -7200 1 -02}
    {2866410000 -10800 0 -03}
    {2879110800 -7200 1 -02}
    {2897859600 -10800 0 -03}
    {2910560400 -7200 1 -02}
    {2929309200 -10800 0 -03}
    {2942010000 -7200 1 -02}
    {2960758800 -10800 0 -03}
    {2974064400 -7200 1 -02}
    {2992208400 -10800 0 -03}
    {3005514000 -7200 1 -02}
    {3023658000 -10800 0 -03}
    {3036963600 -7200 1 -02}
    {3055712400 -10800 0 -03}
    {3068413200 -7200 1 -02}
    {3087162000 -10800 0 -03}
    {3099862800 -7200 1 -02}
    {3118611600 -10800 0 -03}
    {3131917200 -7200 1 -02}
    {3150061200 -10800 0 -03}
    {3163366800 -7200 1 -02}
    {3181510800 -10800 0 -03}
    {3194816400 -7200 1 -02}
    {3212960400 -10800 0 -03}
    {3226266000 -7200 1 -02}
    {3245014800 -10800 0 -03}
    {3257715600 -7200 1 -02}
    {3276464400 -10800 0 -03}
    {3289165200 -7200 1 -02}
    {3307914000 -10800 0 -03}
    {3321219600 -7200 1 -02}
    {3339363600 -10800 0 -03}
    {3352669200 -7200 1 -02}
    {3370813200 -10800 0 -03}
    {3384118800 -7200 1 -02}
    {3402867600 -10800 0 -03}
    {3415568400 -7200 1 -02}
    {3434317200 -10800 0 -03}
    {3447018000 -7200 1 -02}
    {3465766800 -10800 0 -03}
    {3479072400 -7200 1 -02}
    {3497216400 -10800 0 -03}
    {3510522000 -7200 1 -02}
    {3528666000 -10800 0 -03}
    {3541971600 -7200 1 -02}
    {3560115600 -10800 0 -03}
    {3573421200 -7200 1 -02}
    {3592170000 -10800 0 -03}
    {3604870800 -7200 1 -02}
    {3623619600 -10800 0 -03}
    {3636320400 -7200 1 -02}
    {3655069200 -10800 0 -03}
    {3668374800 -7200 1 -02}
    {3686518800 -10800 0 -03}
    {3699824400 -7200 1 -02}
    {3717968400 -10800 0 -03}
    {3731274000 -7200 1 -02}
    {3750022800 -10800 0 -03}
    {3762723600 -7200 1 -02}
    {3781472400 -10800 0 -03}
    {3794173200 -7200 1 -02}
    {3812922000 -10800 0 -03}
    {3825622800 -7200 1 -02}
    {3844371600 -10800 0 -03}
    {3857677200 -7200 1 -02}
    {3875821200 -10800 0 -03}
    {3889126800 -7200 1 -02}
    {3907270800 -10800 0 -03}
    {3920576400 -7200 1 -02}
    {3939325200 -10800 0 -03}
    {3952026000 -7200 1 -02}
    {3970774800 -10800 0 -03}
    {3983475600 -7200 1 -02}
    {4002224400 -10800 0 -03}
    {4015530000 -7200 1 -02}
    {4033674000 -10800 0 -03}
    {4046979600 -7200 1 -02}
    {4065123600 -10800 0 -03}
    {4078429200 -7200 1 -02}
    {4096573200 -10800 0 -03}
}

Changes to library/tzdata/America/Grand_Turk.

73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 0 AST}

    {1520751600 -14400 0 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}







|
>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446361200 -14400 0 AST}
    {1520751600 -14400 0 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}

Changes to library/tzdata/America/Grenada.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Grenada) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Grenada) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Guadeloupe.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Guadeloupe) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Guadeloupe) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Guyana.

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Guyana) {
    {-9223372036854775808 -13959 0 LMT}
    {-1843589241 -14400 0 -04}
    {-1730577600 -13500 0 -0345}
    {176096700 -10800 0 -03}
    {701841600 -14400 0 -04}
}



|
<
|
|
|

1
2
3
4

5
6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Guyana) {
    {-9223372036854775808 -13960 0 LMT}

    {-1730578040 -13500 0 -0345}
    {176010300 -10800 0 -03}
    {662698800 -14400 0 -04}
}

Changes to library/tzdata/America/Hermosillo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Hermosillo) {
    {-9223372036854775808 -26632 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Hermosillo) {
    {-9223372036854775808 -26632 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}

Changes to library/tzdata/America/Indiana/Tell_City.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Indiana/Tell_City) {
    {-9223372036854775808 -20823 0 LMT}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {-757360800 -21600 0 CST}






    {-462996000 -18000 1 CDT}
    {-450291600 -21600 0 CST}
    {-431539200 -18000 1 CDT}
    {-418237200 -21600 0 CST}
    {-400089600 -18000 1 CDT}
    {-386787600 -21600 0 CST}
    {-368640000 -18000 1 CDT}
    {-355338000 -21600 0 CST}
    {-337190400 -18000 1 CDT}
    {-323888400 -21600 0 CST}
    {-305740800 -18000 1 CDT}
    {-292438800 -21600 0 CST}
    {-273686400 -18000 1 CDT}
    {-257965200 -21600 0 CST}
    {-242236800 -18000 1 CDT}
    {-226515600 -21600 0 CST}
    {-210787200 -18000 1 CDT}
    {-195066000 -21600 0 CST}
    {-179337600 -18000 0 EST}
    {-68662800 -21600 0 CST}
    {-52934400 -18000 1 CDT}
    {-37213200 -21600 0 CST}
    {-21484800 -14400 0 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {31554000 -18000 0 EST}
    {1143961200 -21600 0 CST}
    {1143964800 -18000 1 CDT}
    {1162105200 -21600 0 CST}













>
>
>
>
>
>











|

|





<
|
<
|







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Indiana/Tell_City) {
    {-9223372036854775808 -20823 0 LMT}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {-757360800 -21600 0 CST}
    {-747244800 -18000 1 CDT}
    {-733942800 -21600 0 CST}
    {-526492800 -18000 1 CDT}
    {-513190800 -21600 0 CST}
    {-495043200 -18000 1 CDT}
    {-481741200 -21600 0 CST}
    {-462996000 -18000 1 CDT}
    {-450291600 -21600 0 CST}
    {-431539200 -18000 1 CDT}
    {-418237200 -21600 0 CST}
    {-400089600 -18000 1 CDT}
    {-386787600 -21600 0 CST}
    {-368640000 -18000 1 CDT}
    {-355338000 -21600 0 CST}
    {-337190400 -18000 1 CDT}
    {-323888400 -21600 0 CST}
    {-305740800 -18000 1 CDT}
    {-289414800 -21600 0 CST}
    {-273686400 -18000 1 CDT}
    {-260989200 -21600 0 CST}
    {-242236800 -18000 1 CDT}
    {-226515600 -21600 0 CST}
    {-210787200 -18000 1 CDT}
    {-195066000 -21600 0 CST}
    {-179337600 -18000 0 EST}

    {-31518000 -18000 0 EST}

    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {31554000 -18000 0 EST}
    {1143961200 -21600 0 CST}
    {1143964800 -18000 1 CDT}
    {1162105200 -21600 0 CST}

Changes to library/tzdata/America/Inuvik.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Inuvik) {
    {-9223372036854775808 0 0 -00}
    {-536457600 -28800 0 PST}
    {73476000 -25200 1 PDT}
    {89197200 -28800 0 PST}
    {104925600 -25200 1 PDT}
    {120646800 -28800 0 PST}
    {136375200 -25200 1 PDT}
    {152096400 -28800 0 PST}
    {167824800 -25200 1 PDT}
    {183546000 -28800 0 PST}
    {199274400 -25200 1 PDT}
    {215600400 -28800 0 PST}
    {230724000 -25200 1 PDT}
    {247050000 -28800 0 PST}
    {262778400 -25200 1 PDT}
    {278499600 -28800 0 PST}
    {294228000 -21600 0 MDT}
    {309945600 -25200 0 MST}
    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}





|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6




7










8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Inuvik) {
    {-9223372036854775808 0 0 -00}
    {-536457600 -28800 0 PST}
    {-147888000 -21600 1 PDDT}




    {-131558400 -28800 0 PST}










    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}

Changes to library/tzdata/America/Iqaluit.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Iqaluit) {
    {-9223372036854775808 0 0 -00}
    {-865296000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}







|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<







1
2
3
4
5
6
7
8










9




10
11
12
13
14
15
16
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Iqaluit) {
    {-9223372036854775808 0 0 -00}
    {-865296000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {-147898800 -10800 1 EDDT}










    {-131569200 -18000 0 EST}




    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}

Changes to library/tzdata/America/Kentucky/Louisville.

13
14
15
16
17
18
19
20
21
22



23
24
25
26
27
28
29
    {-905097600 -18000 1 CDT}
    {-891795600 -21600 0 CST}
    {-883591200 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {-757360800 -21600 0 CST}
    {-747251940 -18000 1 CDT}
    {-744224400 -21600 0 CST}
    {-620841600 -18000 1 CDT}



    {-608144400 -21600 0 CST}
    {-589392000 -18000 1 CDT}
    {-576090000 -21600 0 CST}
    {-557942400 -18000 1 CDT}
    {-544640400 -21600 0 CST}
    {-526492800 -18000 1 CDT}
    {-513190800 -21600 0 CST}







|

|
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    {-905097600 -18000 1 CDT}
    {-891795600 -21600 0 CST}
    {-883591200 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {-757360800 -21600 0 CST}
    {-747244800 -18000 1 CDT}
    {-744224400 -21600 0 CST}
    {-715795200 -18000 1 CDT}
    {-684349200 -18000 1 CDT}
    {-652899600 -18000 1 CDT}
    {-620845200 -18000 1 CDT}
    {-608144400 -21600 0 CST}
    {-589392000 -18000 1 CDT}
    {-576090000 -21600 0 CST}
    {-557942400 -18000 1 CDT}
    {-544640400 -21600 0 CST}
    {-526492800 -18000 1 CDT}
    {-513190800 -21600 0 CST}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    {-368640000 -18000 1 CDT}
    {-352918800 -21600 0 CST}
    {-337190400 -18000 1 CDT}
    {-321469200 -21600 0 CST}
    {-305740800 -18000 1 CDT}
    {-289414800 -21600 0 CST}
    {-273686400 -18000 1 CDT}
    {-266428800 -18000 0 EST}
    {-63140400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    {-368640000 -18000 1 CDT}
    {-352918800 -21600 0 CST}
    {-337190400 -18000 1 CDT}
    {-321469200 -21600 0 CST}
    {-305740800 -18000 1 CDT}
    {-289414800 -21600 0 CST}
    {-273686400 -18000 1 CDT}
    {-266432400 -18000 0 EST}
    {-63140400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}

Changes to library/tzdata/America/Kralendijk.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Kralendijk) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Kralendijk) $TZData(:America/Curacao)

Changes to library/tzdata/America/Lower_Princes.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Lower_Princes) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Lower_Princes) $TZData(:America/Curacao)

Changes to library/tzdata/America/Marigot.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Marigot) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Marigot) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Matamoros.

1
2
3
4
5
6
7
8
9
10
11
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Matamoros) {
    {-9223372036854775808 -23400 0 LMT}
    {-1514743200 -21600 0 CST}
    {568015200 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {599637600 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}



|







1
2
3
4
5
6
7
8
9
10
11
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Matamoros) {
    {-9223372036854775808 -24000 0 LMT}
    {-1514743200 -21600 0 CST}
    {568015200 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {599637600 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}

Changes to library/tzdata/America/Mazatlan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mazatlan) {
    {-9223372036854775808 -25540 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mazatlan) {
    {-9223372036854775808 -25540 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
61
62
63
64
65
66
67


























































































































































68
    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}
    {1667116800 -25200 0 MST}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}
    {1667116800 -25200 0 MST}
    {1680426000 -21600 1 MDT}
    {1698566400 -25200 0 MST}
    {1712480400 -21600 1 MDT}
    {1730016000 -25200 0 MST}
    {1743930000 -21600 1 MDT}
    {1761465600 -25200 0 MST}
    {1775379600 -21600 1 MDT}
    {1792915200 -25200 0 MST}
    {1806829200 -21600 1 MDT}
    {1824969600 -25200 0 MST}
    {1838278800 -21600 1 MDT}
    {1856419200 -25200 0 MST}
    {1869728400 -21600 1 MDT}
    {1887868800 -25200 0 MST}
    {1901782800 -21600 1 MDT}
    {1919318400 -25200 0 MST}
    {1933232400 -21600 1 MDT}
    {1950768000 -25200 0 MST}
    {1964682000 -21600 1 MDT}
    {1982822400 -25200 0 MST}
    {1996131600 -21600 1 MDT}
    {2014272000 -25200 0 MST}
    {2027581200 -21600 1 MDT}
    {2045721600 -25200 0 MST}
    {2059030800 -21600 1 MDT}
    {2077171200 -25200 0 MST}
    {2091085200 -21600 1 MDT}
    {2108620800 -25200 0 MST}
    {2122534800 -21600 1 MDT}
    {2140070400 -25200 0 MST}
    {2153984400 -21600 1 MDT}
    {2172124800 -25200 0 MST}
    {2185434000 -21600 1 MDT}
    {2203574400 -25200 0 MST}
    {2216883600 -21600 1 MDT}
    {2235024000 -25200 0 MST}
    {2248938000 -21600 1 MDT}
    {2266473600 -25200 0 MST}
    {2280387600 -21600 1 MDT}
    {2297923200 -25200 0 MST}
    {2311837200 -21600 1 MDT}
    {2329372800 -25200 0 MST}
    {2343286800 -21600 1 MDT}
    {2361427200 -25200 0 MST}
    {2374736400 -21600 1 MDT}
    {2392876800 -25200 0 MST}
    {2406186000 -21600 1 MDT}
    {2424326400 -25200 0 MST}
    {2438240400 -21600 1 MDT}
    {2455776000 -25200 0 MST}
    {2469690000 -21600 1 MDT}
    {2487225600 -25200 0 MST}
    {2501139600 -21600 1 MDT}
    {2519280000 -25200 0 MST}
    {2532589200 -21600 1 MDT}
    {2550729600 -25200 0 MST}
    {2564038800 -21600 1 MDT}
    {2582179200 -25200 0 MST}
    {2596093200 -21600 1 MDT}
    {2613628800 -25200 0 MST}
    {2627542800 -21600 1 MDT}
    {2645078400 -25200 0 MST}
    {2658992400 -21600 1 MDT}
    {2676528000 -25200 0 MST}
    {2690442000 -21600 1 MDT}
    {2708582400 -25200 0 MST}
    {2721891600 -21600 1 MDT}
    {2740032000 -25200 0 MST}
    {2753341200 -21600 1 MDT}
    {2771481600 -25200 0 MST}
    {2785395600 -21600 1 MDT}
    {2802931200 -25200 0 MST}
    {2816845200 -21600 1 MDT}
    {2834380800 -25200 0 MST}
    {2848294800 -21600 1 MDT}
    {2866435200 -25200 0 MST}
    {2879744400 -21600 1 MDT}
    {2897884800 -25200 0 MST}
    {2911194000 -21600 1 MDT}
    {2929334400 -25200 0 MST}
    {2942643600 -21600 1 MDT}
    {2960784000 -25200 0 MST}
    {2974698000 -21600 1 MDT}
    {2992233600 -25200 0 MST}
    {3006147600 -21600 1 MDT}
    {3023683200 -25200 0 MST}
    {3037597200 -21600 1 MDT}
    {3055737600 -25200 0 MST}
    {3069046800 -21600 1 MDT}
    {3087187200 -25200 0 MST}
    {3100496400 -21600 1 MDT}
    {3118636800 -25200 0 MST}
    {3132550800 -21600 1 MDT}
    {3150086400 -25200 0 MST}
    {3164000400 -21600 1 MDT}
    {3181536000 -25200 0 MST}
    {3195450000 -21600 1 MDT}
    {3212985600 -25200 0 MST}
    {3226899600 -21600 1 MDT}
    {3245040000 -25200 0 MST}
    {3258349200 -21600 1 MDT}
    {3276489600 -25200 0 MST}
    {3289798800 -21600 1 MDT}
    {3307939200 -25200 0 MST}
    {3321853200 -21600 1 MDT}
    {3339388800 -25200 0 MST}
    {3353302800 -21600 1 MDT}
    {3370838400 -25200 0 MST}
    {3384752400 -21600 1 MDT}
    {3402892800 -25200 0 MST}
    {3416202000 -21600 1 MDT}
    {3434342400 -25200 0 MST}
    {3447651600 -21600 1 MDT}
    {3465792000 -25200 0 MST}
    {3479706000 -21600 1 MDT}
    {3497241600 -25200 0 MST}
    {3511155600 -21600 1 MDT}
    {3528691200 -25200 0 MST}
    {3542605200 -21600 1 MDT}
    {3560140800 -25200 0 MST}
    {3574054800 -21600 1 MDT}
    {3592195200 -25200 0 MST}
    {3605504400 -21600 1 MDT}
    {3623644800 -25200 0 MST}
    {3636954000 -21600 1 MDT}
    {3655094400 -25200 0 MST}
    {3669008400 -21600 1 MDT}
    {3686544000 -25200 0 MST}
    {3700458000 -21600 1 MDT}
    {3717993600 -25200 0 MST}
    {3731907600 -21600 1 MDT}
    {3750048000 -25200 0 MST}
    {3763357200 -21600 1 MDT}
    {3781497600 -25200 0 MST}
    {3794806800 -21600 1 MDT}
    {3812947200 -25200 0 MST}
    {3826256400 -21600 1 MDT}
    {3844396800 -25200 0 MST}
    {3858310800 -21600 1 MDT}
    {3875846400 -25200 0 MST}
    {3889760400 -21600 1 MDT}
    {3907296000 -25200 0 MST}
    {3921210000 -21600 1 MDT}
    {3939350400 -25200 0 MST}
    {3952659600 -21600 1 MDT}
    {3970800000 -25200 0 MST}
    {3984109200 -21600 1 MDT}
    {4002249600 -25200 0 MST}
    {4016163600 -21600 1 MDT}
    {4033699200 -25200 0 MST}
    {4047613200 -21600 1 MDT}
    {4065148800 -25200 0 MST}
    {4079062800 -21600 1 MDT}
    {4096598400 -25200 0 MST}
}

Changes to library/tzdata/America/Merida.

55
56
57
58
59
60
61


























































































































































62
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Metlakatla.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    {436356000 -28800 0 PST}
    {1446372000 -32400 0 AKST}
    {1457866800 -28800 1 AKDT}
    {1478426400 -32400 0 AKST}
    {1489316400 -28800 1 AKDT}
    {1509876000 -32400 0 AKST}
    {1520766000 -28800 1 AKDT}
    {1541329200 -28800 0 PST}
    {1547978400 -32400 0 AKST}
    {1552215600 -28800 1 AKDT}
    {1572775200 -32400 0 AKST}
    {1583665200 -28800 1 AKDT}
    {1604224800 -32400 0 AKST}
    {1615719600 -28800 1 AKDT}
    {1636279200 -32400 0 AKST}
    {1647169200 -28800 1 AKDT}







<
|







42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
    {436356000 -28800 0 PST}
    {1446372000 -32400 0 AKST}
    {1457866800 -28800 1 AKDT}
    {1478426400 -32400 0 AKST}
    {1489316400 -28800 1 AKDT}
    {1509876000 -32400 0 AKST}
    {1520766000 -28800 1 AKDT}

    {1541325600 -32400 0 AKST}
    {1552215600 -28800 1 AKDT}
    {1572775200 -32400 0 AKST}
    {1583665200 -28800 1 AKDT}
    {1604224800 -32400 0 AKST}
    {1615719600 -28800 1 AKDT}
    {1636279200 -32400 0 AKST}
    {1647169200 -28800 1 AKDT}

Changes to library/tzdata/America/Mexico_City.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mexico_City) {
    {-9223372036854775808 -23796 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-975261600 -18000 1 CDT}
    {-963169200 -21600 0 CST}
    {-917114400 -18000 1 CDT}
    {-907354800 -21600 0 CST}
    {-821901600 -18000 1 CWT}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mexico_City) {
    {-9223372036854775808 -23796 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-975261600 -18000 1 CDT}
    {-963169200 -21600 0 CST}
    {-917114400 -18000 1 CDT}
    {-907354800 -21600 0 CST}
    {-821901600 -18000 1 CWT}
67
68
69
70
71
72
73


























































































































































74
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Monterrey.

57
58
59
60
61
62
63


























































































































































64
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Montserrat.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Montserrat) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Montserrat) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Nassau.

1
2
3
4
5




















































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto
}
set TZData(:America/Nassau) $TZData(:America/Toronto)





















































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Nassau) {
    {-9223372036854775808 -18570 0 LMT}
    {-1825095030 -18000 0 EST}
    {-179341200 -14400 1 EDT}
    {-163620000 -18000 0 EST}
    {-147891600 -14400 1 EDT}
    {-131565600 -18000 0 EST}
    {-116442000 -14400 1 EDT}
    {-100116000 -18000 0 EST}
    {-84387600 -14400 1 EDT}
    {-68666400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {41410800 -14400 1 EDT}
    {57736800 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {189320400 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Nipigon.

1
2
3
4
5





































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto
}
set TZData(:America/Nipigon) $TZData(:America/Toronto)






































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Nipigon) {
    {-9223372036854775808 -21184 0 LMT}
    {-2366734016 -18000 0 EST}
    {-1632070800 -14400 1 EDT}
    {-1615140000 -18000 0 EST}
    {-923252400 -14400 1 EDT}
    {-880218000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Deleted library/tzdata/America/Nuuk.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Nuuk) {
    {-9223372036854775808 -12416 0 LMT}
    {-1686083584 -10800 0 -03}
    {323845200 -7200 0 -02}
    {338950800 -10800 0 -03}
    {354675600 -7200 1 -02}
    {370400400 -10800 0 -03}
    {386125200 -7200 1 -02}
    {401850000 -10800 0 -03}
    {417574800 -7200 1 -02}
    {433299600 -10800 0 -03}
    {449024400 -7200 1 -02}
    {465354000 -10800 0 -03}
    {481078800 -7200 1 -02}
    {496803600 -10800 0 -03}
    {512528400 -7200 1 -02}
    {528253200 -10800 0 -03}
    {543978000 -7200 1 -02}
    {559702800 -10800 0 -03}
    {575427600 -7200 1 -02}
    {591152400 -10800 0 -03}
    {606877200 -7200 1 -02}
    {622602000 -10800 0 -03}
    {638326800 -7200 1 -02}
    {654656400 -10800 0 -03}
    {670381200 -7200 1 -02}
    {686106000 -10800 0 -03}
    {701830800 -7200 1 -02}
    {717555600 -10800 0 -03}
    {733280400 -7200 1 -02}
    {749005200 -10800 0 -03}
    {764730000 -7200 1 -02}
    {780454800 -10800 0 -03}
    {796179600 -7200 1 -02}
    {811904400 -10800 0 -03}
    {828234000 -7200 1 -02}
    {846378000 -10800 0 -03}
    {859683600 -7200 1 -02}
    {877827600 -10800 0 -03}
    {891133200 -7200 1 -02}
    {909277200 -10800 0 -03}
    {922582800 -7200 1 -02}
    {941331600 -10800 0 -03}
    {954032400 -7200 1 -02}
    {972781200 -10800 0 -03}
    {985482000 -7200 1 -02}
    {1004230800 -10800 0 -03}
    {1017536400 -7200 1 -02}
    {1035680400 -10800 0 -03}
    {1048986000 -7200 1 -02}
    {1067130000 -10800 0 -03}
    {1080435600 -7200 1 -02}
    {1099184400 -10800 0 -03}
    {1111885200 -7200 1 -02}
    {1130634000 -10800 0 -03}
    {1143334800 -7200 1 -02}
    {1162083600 -10800 0 -03}
    {1174784400 -7200 1 -02}
    {1193533200 -10800 0 -03}
    {1206838800 -7200 1 -02}
    {1224982800 -10800 0 -03}
    {1238288400 -7200 1 -02}
    {1256432400 -10800 0 -03}
    {1269738000 -7200 1 -02}
    {1288486800 -10800 0 -03}
    {1301187600 -7200 1 -02}
    {1319936400 -10800 0 -03}
    {1332637200 -7200 1 -02}
    {1351386000 -10800 0 -03}
    {1364691600 -7200 1 -02}
    {1382835600 -10800 0 -03}
    {1396141200 -7200 1 -02}
    {1414285200 -10800 0 -03}
    {1427590800 -7200 1 -02}
    {1445734800 -10800 0 -03}
    {1459040400 -7200 1 -02}
    {1477789200 -10800 0 -03}
    {1490490000 -7200 1 -02}
    {1509238800 -10800 0 -03}
    {1521939600 -7200 1 -02}
    {1540688400 -10800 0 -03}
    {1553994000 -7200 1 -02}
    {1572138000 -10800 0 -03}
    {1585443600 -7200 1 -02}
    {1603587600 -10800 0 -03}
    {1616893200 -7200 1 -02}
    {1635642000 -10800 0 -03}
    {1648342800 -7200 1 -02}
    {1667091600 -10800 0 -03}
    {1679792400 -7200 0 -02}
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































Changes to library/tzdata/America/Ojinaga.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Ojinaga) {
    {-9223372036854775808 -25060 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Ojinaga) {
    {-9223372036854775808 -25060 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667120400 -21600 0 CST}
    {1669788000 -21600 0 CST}
    {1678608000 -18000 1 CDT}
    {1699167600 -21600 0 CST}
    {1710057600 -18000 1 CDT}
    {1730617200 -21600 0 CST}
    {1741507200 -18000 1 CDT}
    {1762066800 -21600 0 CST}
    {1772956800 -18000 1 CDT}
    {1793516400 -21600 0 CST}
    {1805011200 -18000 1 CDT}
    {1825570800 -21600 0 CST}
    {1836460800 -18000 1 CDT}
    {1857020400 -21600 0 CST}
    {1867910400 -18000 1 CDT}
    {1888470000 -21600 0 CST}
    {1899360000 -18000 1 CDT}
    {1919919600 -21600 0 CST}
    {1930809600 -18000 1 CDT}
    {1951369200 -21600 0 CST}
    {1962864000 -18000 1 CDT}
    {1983423600 -21600 0 CST}
    {1994313600 -18000 1 CDT}
    {2014873200 -21600 0 CST}
    {2025763200 -18000 1 CDT}
    {2046322800 -21600 0 CST}
    {2057212800 -18000 1 CDT}
    {2077772400 -21600 0 CST}

    {2088662400 -18000 1 CDT}
    {2109222000 -21600 0 CST}
    {2120112000 -18000 1 CDT}
    {2140671600 -21600 0 CST}
    {2152166400 -18000 1 CDT}
    {2172726000 -21600 0 CST}
    {2183616000 -18000 1 CDT}
    {2204175600 -21600 0 CST}
    {2215065600 -18000 1 CDT}
    {2235625200 -21600 0 CST}
    {2246515200 -18000 1 CDT}
    {2267074800 -21600 0 CST}
    {2277964800 -18000 1 CDT}
    {2298524400 -21600 0 CST}
    {2309414400 -18000 1 CDT}
    {2329974000 -21600 0 CST}
    {2341468800 -18000 1 CDT}
    {2362028400 -21600 0 CST}
    {2372918400 -18000 1 CDT}
    {2393478000 -21600 0 CST}
    {2404368000 -18000 1 CDT}
    {2424927600 -21600 0 CST}
    {2435817600 -18000 1 CDT}
    {2456377200 -21600 0 CST}
    {2467267200 -18000 1 CDT}
    {2487826800 -21600 0 CST}
    {2499321600 -18000 1 CDT}
    {2519881200 -21600 0 CST}
    {2530771200 -18000 1 CDT}
    {2551330800 -21600 0 CST}
    {2562220800 -18000 1 CDT}
    {2582780400 -21600 0 CST}
    {2593670400 -18000 1 CDT}
    {2614230000 -21600 0 CST}
    {2625120000 -18000 1 CDT}
    {2645679600 -21600 0 CST}
    {2656569600 -18000 1 CDT}
    {2677129200 -21600 0 CST}
    {2688624000 -18000 1 CDT}
    {2709183600 -21600 0 CST}

    {2720073600 -18000 1 CDT}
    {2740633200 -21600 0 CST}
    {2751523200 -18000 1 CDT}
    {2772082800 -21600 0 CST}
    {2782972800 -18000 1 CDT}
    {2803532400 -21600 0 CST}
    {2814422400 -18000 1 CDT}
    {2834982000 -21600 0 CST}
    {2846476800 -18000 1 CDT}
    {2867036400 -21600 0 CST}
    {2877926400 -18000 1 CDT}
    {2898486000 -21600 0 CST}
    {2909376000 -18000 1 CDT}
    {2929935600 -21600 0 CST}
    {2940825600 -18000 1 CDT}
    {2961385200 -21600 0 CST}
    {2972275200 -18000 1 CDT}
    {2992834800 -21600 0 CST}
    {3003724800 -18000 1 CDT}
    {3024284400 -21600 0 CST}
    {3035779200 -18000 1 CDT}
    {3056338800 -21600 0 CST}
    {3067228800 -18000 1 CDT}
    {3087788400 -21600 0 CST}
    {3098678400 -18000 1 CDT}
    {3119238000 -21600 0 CST}
    {3130128000 -18000 1 CDT}
    {3150687600 -21600 0 CST}

    {3161577600 -18000 1 CDT}
    {3182137200 -21600 0 CST}
    {3193027200 -18000 1 CDT}
    {3213586800 -21600 0 CST}
    {3225081600 -18000 1 CDT}
    {3245641200 -21600 0 CST}
    {3256531200 -18000 1 CDT}
    {3277090800 -21600 0 CST}
    {3287980800 -18000 1 CDT}
    {3308540400 -21600 0 CST}
    {3319430400 -18000 1 CDT}
    {3339990000 -21600 0 CST}
    {3350880000 -18000 1 CDT}
    {3371439600 -21600 0 CST}
    {3382934400 -18000 1 CDT}
    {3403494000 -21600 0 CST}
    {3414384000 -18000 1 CDT}
    {3434943600 -21600 0 CST}
    {3445833600 -18000 1 CDT}
    {3466393200 -21600 0 CST}

    {3477283200 -18000 1 CDT}
    {3497842800 -21600 0 CST}
    {3508732800 -18000 1 CDT}
    {3529292400 -21600 0 CST}
    {3540182400 -18000 1 CDT}
    {3560742000 -21600 0 CST}
    {3572236800 -18000 1 CDT}
    {3592796400 -21600 0 CST}
    {3603686400 -18000 1 CDT}
    {3624246000 -21600 0 CST}
    {3635136000 -18000 1 CDT}
    {3655695600 -21600 0 CST}
    {3666585600 -18000 1 CDT}
    {3687145200 -21600 0 CST}
    {3698035200 -18000 1 CDT}
    {3718594800 -21600 0 CST}
    {3730089600 -18000 1 CDT}
    {3750649200 -21600 0 CST}
    {3761539200 -18000 1 CDT}
    {3782098800 -21600 0 CST}
    {3792988800 -18000 1 CDT}
    {3813548400 -21600 0 CST}
    {3824438400 -18000 1 CDT}
    {3844998000 -21600 0 CST}
    {3855888000 -18000 1 CDT}
    {3876447600 -21600 0 CST}
    {3887337600 -18000 1 CDT}
    {3907897200 -21600 0 CST}
    {3919392000 -18000 1 CDT}
    {3939951600 -21600 0 CST}
    {3950841600 -18000 1 CDT}
    {3971401200 -21600 0 CST}

    {3982291200 -18000 1 CDT}
    {4002850800 -21600 0 CST}
    {4013740800 -18000 1 CDT}
    {4034300400 -21600 0 CST}
    {4045190400 -18000 1 CDT}
    {4065750000 -21600 0 CST}
    {4076640000 -18000 1 CDT}
    {4097199600 -21600 0 CST}
}







|
|
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667721600 -25200 0 MST}
    {1678611600 -21600 1 MDT}

    {1699171200 -25200 0 MST}

    {1710061200 -21600 1 MDT}
    {1730620800 -25200 0 MST}
    {1741510800 -21600 1 MDT}
    {1762070400 -25200 0 MST}
    {1772960400 -21600 1 MDT}
    {1793520000 -25200 0 MST}
    {1805014800 -21600 1 MDT}
    {1825574400 -25200 0 MST}
    {1836464400 -21600 1 MDT}
    {1857024000 -25200 0 MST}
    {1867914000 -21600 1 MDT}
    {1888473600 -25200 0 MST}
    {1899363600 -21600 1 MDT}
    {1919923200 -25200 0 MST}
    {1930813200 -21600 1 MDT}
    {1951372800 -25200 0 MST}
    {1962867600 -21600 1 MDT}
    {1983427200 -25200 0 MST}
    {1994317200 -21600 1 MDT}
    {2014876800 -25200 0 MST}
    {2025766800 -21600 1 MDT}
    {2046326400 -25200 0 MST}
    {2057216400 -21600 1 MDT}
    {2077776000 -25200 0 MST}
    {2088666000 -21600 1 MDT}
    {2109225600 -25200 0 MST}
    {2120115600 -21600 1 MDT}
    {2140675200 -25200 0 MST}
    {2152170000 -21600 1 MDT}
    {2172729600 -25200 0 MST}
    {2183619600 -21600 1 MDT}
    {2204179200 -25200 0 MST}
    {2215069200 -21600 1 MDT}
    {2235628800 -25200 0 MST}

    {2246518800 -21600 1 MDT}
    {2267078400 -25200 0 MST}
    {2277968400 -21600 1 MDT}
    {2298528000 -25200 0 MST}
    {2309418000 -21600 1 MDT}
    {2329977600 -25200 0 MST}
    {2341472400 -21600 1 MDT}
    {2362032000 -25200 0 MST}
    {2372922000 -21600 1 MDT}
    {2393481600 -25200 0 MST}
    {2404371600 -21600 1 MDT}
    {2424931200 -25200 0 MST}
    {2435821200 -21600 1 MDT}
    {2456380800 -25200 0 MST}
    {2467270800 -21600 1 MDT}
    {2487830400 -25200 0 MST}
    {2499325200 -21600 1 MDT}
    {2519884800 -25200 0 MST}
    {2530774800 -21600 1 MDT}
    {2551334400 -25200 0 MST}
    {2562224400 -21600 1 MDT}
    {2582784000 -25200 0 MST}
    {2593674000 -21600 1 MDT}
    {2614233600 -25200 0 MST}
    {2625123600 -21600 1 MDT}
    {2645683200 -25200 0 MST}
    {2656573200 -21600 1 MDT}
    {2677132800 -25200 0 MST}
    {2688627600 -21600 1 MDT}
    {2709187200 -25200 0 MST}
    {2720077200 -21600 1 MDT}
    {2740636800 -25200 0 MST}
    {2751526800 -21600 1 MDT}
    {2772086400 -25200 0 MST}
    {2782976400 -21600 1 MDT}
    {2803536000 -25200 0 MST}
    {2814426000 -21600 1 MDT}
    {2834985600 -25200 0 MST}
    {2846480400 -21600 1 MDT}
    {2867040000 -25200 0 MST}

    {2877930000 -21600 1 MDT}
    {2898489600 -25200 0 MST}
    {2909379600 -21600 1 MDT}
    {2929939200 -25200 0 MST}
    {2940829200 -21600 1 MDT}
    {2961388800 -25200 0 MST}
    {2972278800 -21600 1 MDT}
    {2992838400 -25200 0 MST}
    {3003728400 -21600 1 MDT}
    {3024288000 -25200 0 MST}
    {3035782800 -21600 1 MDT}
    {3056342400 -25200 0 MST}
    {3067232400 -21600 1 MDT}
    {3087792000 -25200 0 MST}
    {3098682000 -21600 1 MDT}
    {3119241600 -25200 0 MST}
    {3130131600 -21600 1 MDT}
    {3150691200 -25200 0 MST}
    {3161581200 -21600 1 MDT}
    {3182140800 -25200 0 MST}
    {3193030800 -21600 1 MDT}
    {3213590400 -25200 0 MST}
    {3225085200 -21600 1 MDT}
    {3245644800 -25200 0 MST}
    {3256534800 -21600 1 MDT}
    {3277094400 -25200 0 MST}
    {3287984400 -21600 1 MDT}
    {3308544000 -25200 0 MST}

    {3319434000 -21600 1 MDT}
    {3339993600 -25200 0 MST}
    {3350883600 -21600 1 MDT}
    {3371443200 -25200 0 MST}
    {3382938000 -21600 1 MDT}
    {3403497600 -25200 0 MST}
    {3414387600 -21600 1 MDT}
    {3434947200 -25200 0 MST}
    {3445837200 -21600 1 MDT}
    {3466396800 -25200 0 MST}
    {3477286800 -21600 1 MDT}
    {3497846400 -25200 0 MST}
    {3508736400 -21600 1 MDT}
    {3529296000 -25200 0 MST}
    {3540186000 -21600 1 MDT}
    {3560745600 -25200 0 MST}

    {3572240400 -21600 1 MDT}
    {3592800000 -25200 0 MST}
    {3603690000 -21600 1 MDT}
    {3624249600 -25200 0 MST}
    {3635139600 -21600 1 MDT}
    {3655699200 -25200 0 MST}
    {3666589200 -21600 1 MDT}
    {3687148800 -25200 0 MST}
    {3698038800 -21600 1 MDT}
    {3718598400 -25200 0 MST}
    {3730093200 -21600 1 MDT}
    {3750652800 -25200 0 MST}
    {3761542800 -21600 1 MDT}
    {3782102400 -25200 0 MST}
    {3792992400 -21600 1 MDT}
    {3813552000 -25200 0 MST}
    {3824442000 -21600 1 MDT}
    {3845001600 -25200 0 MST}
    {3855891600 -21600 1 MDT}
    {3876451200 -25200 0 MST}
    {3887341200 -21600 1 MDT}
    {3907900800 -25200 0 MST}
    {3919395600 -21600 1 MDT}
    {3939955200 -25200 0 MST}
    {3950845200 -21600 1 MDT}
    {3971404800 -25200 0 MST}
    {3982294800 -21600 1 MDT}
    {4002854400 -25200 0 MST}
    {4013744400 -21600 1 MDT}
    {4034304000 -25200 0 MST}
    {4045194000 -21600 1 MDT}
    {4065753600 -25200 0 MST}
    {4076643600 -21600 1 MDT}
    {4097203200 -25200 0 MST}
}

Changes to library/tzdata/America/Pangnirtung.

1
2
3
4
5

























































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Iqaluit)]} {
    LoadTimeZoneFile America/Iqaluit
}
set TZData(:America/Pangnirtung) $TZData(:America/Iqaluit)


























































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Pangnirtung) {
    {-9223372036854775808 0 0 -00}
    {-1546300800 -14400 0 AST}
    {-880221600 -10800 1 AWT}
    {-769395600 -10800 1 APT}
    {-765399600 -14400 0 AST}
    {-147902400 -7200 1 ADDT}
    {-131572800 -14400 0 AST}
    {325663200 -10800 1 ADT}
    {341384400 -14400 0 AST}
    {357112800 -10800 1 ADT}
    {372834000 -14400 0 AST}
    {388562400 -10800 1 ADT}
    {404888400 -14400 0 AST}
    {420012000 -10800 1 ADT}
    {436338000 -14400 0 AST}
    {452066400 -10800 1 ADT}
    {467787600 -14400 0 AST}
    {483516000 -10800 1 ADT}
    {499237200 -14400 0 AST}
    {514965600 -10800 1 ADT}
    {530686800 -14400 0 AST}
    {544600800 -10800 1 ADT}
    {562136400 -14400 0 AST}
    {576050400 -10800 1 ADT}
    {594190800 -14400 0 AST}
    {607500000 -10800 1 ADT}
    {625640400 -14400 0 AST}
    {638949600 -10800 1 ADT}
    {657090000 -14400 0 AST}
    {671004000 -10800 1 ADT}
    {688539600 -14400 0 AST}
    {702453600 -10800 1 ADT}
    {719989200 -14400 0 AST}
    {733903200 -10800 1 ADT}
    {752043600 -14400 0 AST}
    {765352800 -10800 1 ADT}
    {783493200 -14400 0 AST}
    {796802400 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972806400 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Port_of_Spain.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Port_of_Spain) $TZData(:America/Puerto_Rico)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Port_of_Spain) {
    {-9223372036854775808 -14764 0 LMT}
    {-1825098836 -14400 0 AST}
}

Changes to library/tzdata/America/Punta_Arenas.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Punta_Arenas) {
    {-9223372036854775808 -17020 0 LMT}
    {-2524504580 -16965 0 SMT}
    {-1892661435 -18000 0 -05}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -04}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}
    {-736632000 -14400 1 -04}
    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}




|
|
|
|
|
|













<







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Punta_Arenas) {
    {-9223372036854775808 -17020 0 LMT}
    {-2524504580 -16966 0 SMT}
    {-1892661434 -18000 0 -05}
    {-1688410800 -16966 0 SMT}
    {-1619205434 -14400 0 -04}
    {-1593806400 -16966 0 SMT}
    {-1335986234 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}

    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}

Changes to library/tzdata/America/Rainy_River.

1
2
3
4
5





































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Winnipeg)]} {
    LoadTimeZoneFile America/Winnipeg
}
set TZData(:America/Rainy_River) $TZData(:America/Winnipeg)






































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Rainy_River) {
    {-9223372036854775808 -22696 0 LMT}
    {-2366732504 -21600 0 CST}
    {-1632067200 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-923248800 -18000 1 CDT}
    {-880214400 -18000 0 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}
    {436345200 -21600 0 CST}
    {452073600 -18000 1 CDT}
    {467794800 -21600 0 CST}
    {483523200 -18000 1 CDT}
    {499244400 -21600 0 CST}
    {514972800 -18000 1 CDT}
    {530694000 -21600 0 CST}
    {544608000 -18000 1 CDT}
    {562143600 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {607507200 -18000 1 CDT}
    {625647600 -21600 0 CST}
    {638956800 -18000 1 CDT}
    {657097200 -21600 0 CST}
    {671011200 -18000 1 CDT}
    {688546800 -21600 0 CST}
    {702460800 -18000 1 CDT}
    {719996400 -21600 0 CST}
    {733910400 -18000 1 CDT}
    {752050800 -21600 0 CST}
    {765360000 -18000 1 CDT}
    {783500400 -21600 0 CST}
    {796809600 -18000 1 CDT}
    {814950000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
    {891763200 -18000 1 CDT}
    {909298800 -21600 0 CST}
    {923212800 -18000 1 CDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972802800 -21600 0 CST}
    {986112000 -18000 1 CDT}
    {1004252400 -21600 0 CST}
    {1018166400 -18000 1 CDT}
    {1035702000 -21600 0 CST}
    {1049616000 -18000 1 CDT}
    {1067151600 -21600 0 CST}
    {1081065600 -18000 1 CDT}
    {1099206000 -21600 0 CST}
    {1112515200 -18000 1 CDT}
    {1130655600 -21600 0 CST}
    {1143964800 -18000 1 CDT}
    {1162105200 -21600 0 CST}
    {1173600000 -18000 1 CDT}
    {1194159600 -21600 0 CST}
    {1205049600 -18000 1 CDT}
    {1225609200 -21600 0 CST}
    {1236499200 -18000 1 CDT}
    {1257058800 -21600 0 CST}
    {1268553600 -18000 1 CDT}
    {1289113200 -21600 0 CST}
    {1300003200 -18000 1 CDT}
    {1320562800 -21600 0 CST}
    {1331452800 -18000 1 CDT}
    {1352012400 -21600 0 CST}
    {1362902400 -18000 1 CDT}
    {1383462000 -21600 0 CST}
    {1394352000 -18000 1 CDT}
    {1414911600 -21600 0 CST}
    {1425801600 -18000 1 CDT}
    {1446361200 -21600 0 CST}
    {1457856000 -18000 1 CDT}
    {1478415600 -21600 0 CST}
    {1489305600 -18000 1 CDT}
    {1509865200 -21600 0 CST}
    {1520755200 -18000 1 CDT}
    {1541314800 -21600 0 CST}
    {1552204800 -18000 1 CDT}
    {1572764400 -21600 0 CST}
    {1583654400 -18000 1 CDT}
    {1604214000 -21600 0 CST}
    {1615708800 -18000 1 CDT}
    {1636268400 -21600 0 CST}
    {1647158400 -18000 1 CDT}
    {1667718000 -21600 0 CST}
    {1678608000 -18000 1 CDT}
    {1699167600 -21600 0 CST}
    {1710057600 -18000 1 CDT}
    {1730617200 -21600 0 CST}
    {1741507200 -18000 1 CDT}
    {1762066800 -21600 0 CST}
    {1772956800 -18000 1 CDT}
    {1793516400 -21600 0 CST}
    {1805011200 -18000 1 CDT}
    {1825570800 -21600 0 CST}
    {1836460800 -18000 1 CDT}
    {1857020400 -21600 0 CST}
    {1867910400 -18000 1 CDT}
    {1888470000 -21600 0 CST}
    {1899360000 -18000 1 CDT}
    {1919919600 -21600 0 CST}
    {1930809600 -18000 1 CDT}
    {1951369200 -21600 0 CST}
    {1962864000 -18000 1 CDT}
    {1983423600 -21600 0 CST}
    {1994313600 -18000 1 CDT}
    {2014873200 -21600 0 CST}
    {2025763200 -18000 1 CDT}
    {2046322800 -21600 0 CST}
    {2057212800 -18000 1 CDT}
    {2077772400 -21600 0 CST}
    {2088662400 -18000 1 CDT}
    {2109222000 -21600 0 CST}
    {2120112000 -18000 1 CDT}
    {2140671600 -21600 0 CST}
    {2152166400 -18000 1 CDT}
    {2172726000 -21600 0 CST}
    {2183616000 -18000 1 CDT}
    {2204175600 -21600 0 CST}
    {2215065600 -18000 1 CDT}
    {2235625200 -21600 0 CST}
    {2246515200 -18000 1 CDT}
    {2267074800 -21600 0 CST}
    {2277964800 -18000 1 CDT}
    {2298524400 -21600 0 CST}
    {2309414400 -18000 1 CDT}
    {2329974000 -21600 0 CST}
    {2341468800 -18000 1 CDT}
    {2362028400 -21600 0 CST}
    {2372918400 -18000 1 CDT}
    {2393478000 -21600 0 CST}
    {2404368000 -18000 1 CDT}
    {2424927600 -21600 0 CST}
    {2435817600 -18000 1 CDT}
    {2456377200 -21600 0 CST}
    {2467267200 -18000 1 CDT}
    {2487826800 -21600 0 CST}
    {2499321600 -18000 1 CDT}
    {2519881200 -21600 0 CST}
    {2530771200 -18000 1 CDT}
    {2551330800 -21600 0 CST}
    {2562220800 -18000 1 CDT}
    {2582780400 -21600 0 CST}
    {2593670400 -18000 1 CDT}
    {2614230000 -21600 0 CST}
    {2625120000 -18000 1 CDT}
    {2645679600 -21600 0 CST}
    {2656569600 -18000 1 CDT}
    {2677129200 -21600 0 CST}
    {2688624000 -18000 1 CDT}
    {2709183600 -21600 0 CST}
    {2720073600 -18000 1 CDT}
    {2740633200 -21600 0 CST}
    {2751523200 -18000 1 CDT}
    {2772082800 -21600 0 CST}
    {2782972800 -18000 1 CDT}
    {2803532400 -21600 0 CST}
    {2814422400 -18000 1 CDT}
    {2834982000 -21600 0 CST}
    {2846476800 -18000 1 CDT}
    {2867036400 -21600 0 CST}
    {2877926400 -18000 1 CDT}
    {2898486000 -21600 0 CST}
    {2909376000 -18000 1 CDT}
    {2929935600 -21600 0 CST}
    {2940825600 -18000 1 CDT}
    {2961385200 -21600 0 CST}
    {2972275200 -18000 1 CDT}
    {2992834800 -21600 0 CST}
    {3003724800 -18000 1 CDT}
    {3024284400 -21600 0 CST}
    {3035779200 -18000 1 CDT}
    {3056338800 -21600 0 CST}
    {3067228800 -18000 1 CDT}
    {3087788400 -21600 0 CST}
    {3098678400 -18000 1 CDT}
    {3119238000 -21600 0 CST}
    {3130128000 -18000 1 CDT}
    {3150687600 -21600 0 CST}
    {3161577600 -18000 1 CDT}
    {3182137200 -21600 0 CST}
    {3193027200 -18000 1 CDT}
    {3213586800 -21600 0 CST}
    {3225081600 -18000 1 CDT}
    {3245641200 -21600 0 CST}
    {3256531200 -18000 1 CDT}
    {3277090800 -21600 0 CST}
    {3287980800 -18000 1 CDT}
    {3308540400 -21600 0 CST}
    {3319430400 -18000 1 CDT}
    {3339990000 -21600 0 CST}
    {3350880000 -18000 1 CDT}
    {3371439600 -21600 0 CST}
    {3382934400 -18000 1 CDT}
    {3403494000 -21600 0 CST}
    {3414384000 -18000 1 CDT}
    {3434943600 -21600 0 CST}
    {3445833600 -18000 1 CDT}
    {3466393200 -21600 0 CST}
    {3477283200 -18000 1 CDT}
    {3497842800 -21600 0 CST}
    {3508732800 -18000 1 CDT}
    {3529292400 -21600 0 CST}
    {3540182400 -18000 1 CDT}
    {3560742000 -21600 0 CST}
    {3572236800 -18000 1 CDT}
    {3592796400 -21600 0 CST}
    {3603686400 -18000 1 CDT}
    {3624246000 -21600 0 CST}
    {3635136000 -18000 1 CDT}
    {3655695600 -21600 0 CST}
    {3666585600 -18000 1 CDT}
    {3687145200 -21600 0 CST}
    {3698035200 -18000 1 CDT}
    {3718594800 -21600 0 CST}
    {3730089600 -18000 1 CDT}
    {3750649200 -21600 0 CST}
    {3761539200 -18000 1 CDT}
    {3782098800 -21600 0 CST}
    {3792988800 -18000 1 CDT}
    {3813548400 -21600 0 CST}
    {3824438400 -18000 1 CDT}
    {3844998000 -21600 0 CST}
    {3855888000 -18000 1 CDT}
    {3876447600 -21600 0 CST}
    {3887337600 -18000 1 CDT}
    {3907897200 -21600 0 CST}
    {3919392000 -18000 1 CDT}
    {3939951600 -21600 0 CST}
    {3950841600 -18000 1 CDT}
    {3971401200 -21600 0 CST}
    {3982291200 -18000 1 CDT}
    {4002850800 -21600 0 CST}
    {4013740800 -18000 1 CDT}
    {4034300400 -21600 0 CST}
    {4045190400 -18000 1 CDT}
    {4065750000 -21600 0 CST}
    {4076640000 -18000 1 CDT}
    {4097199600 -21600 0 CST}
}

Changes to library/tzdata/America/Rankin_Inlet.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Rankin_Inlet) {
    {-9223372036854775808 0 0 -00}
    {-410227200 -21600 0 CST}
    {73468800 -18000 1 CDT}
    {89190000 -21600 0 CST}
    {104918400 -18000 1 CDT}
    {120639600 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}





|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6


7












8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Rankin_Inlet) {
    {-9223372036854775808 0 0 -00}
    {-410227200 -21600 0 CST}
    {-147895200 -14400 1 CDDT}


    {-131565600 -21600 0 CST}












    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}

Changes to library/tzdata/America/Resolute.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Resolute) {
    {-9223372036854775808 0 0 -00}
    {-704937600 -21600 0 CST}
    {73468800 -18000 1 CDT}
    {89190000 -21600 0 CST}
    {104918400 -18000 1 CDT}
    {120639600 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}





|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6


7












8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Resolute) {
    {-9223372036854775808 0 0 -00}
    {-704937600 -21600 0 CST}
    {-147895200 -14400 1 CDDT}


    {-131565600 -21600 0 CST}












    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}

Changes to library/tzdata/America/Santiago.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Santiago) {
    {-9223372036854775808 -16965 0 LMT}
    {-2524504635 -16965 0 SMT}
    {-1892661435 -18000 0 -05}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -04}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}
    {-740520000 -10800 1 -03}
    {-736635600 -14400 1 -04}
    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}



|
|
|
|
|
|
|














|







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Santiago) {
    {-9223372036854775808 -16966 0 LMT}
    {-2524504634 -16966 0 SMT}
    {-1892661434 -18000 0 -05}
    {-1688410800 -16966 0 SMT}
    {-1619205434 -14400 0 -04}
    {-1593806400 -16966 0 SMT}
    {-1335986234 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}
    {-740520000 -10800 1 -03}
    {-736376400 -14400 0 -04}
    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    {1410062400 -10800 1 -04}
    {1463281200 -14400 0 -04}
    {1471147200 -10800 1 -04}
    {1494730800 -14400 0 -04}
    {1502596800 -10800 1 -04}
    {1526180400 -14400 0 -04}
    {1534046400 -10800 1 -04}
    {1554606000 -14400 0 -04}
    {1567915200 -10800 1 -04}
    {1586055600 -14400 0 -04}
    {1599364800 -10800 1 -04}
    {1617505200 -14400 0 -04}
    {1630814400 -10800 1 -04}
    {1648954800 -14400 0 -04}
    {1662868800 -10800 1 -04}
    {1680404400 -14400 0 -04}
    {1693713600 -10800 1 -04}
    {1712458800 -14400 0 -04}
    {1725768000 -10800 1 -04}
    {1743908400 -14400 0 -04}
    {1757217600 -10800 1 -04}
    {1775358000 -14400 0 -04}
    {1788667200 -10800 1 -04}
    {1806807600 -14400 0 -04}
    {1820116800 -10800 1 -04}
    {1838257200 -14400 0 -04}
    {1851566400 -10800 1 -04}
    {1870311600 -14400 0 -04}
    {1883016000 -10800 1 -04}
    {1901761200 -14400 0 -04}
    {1915070400 -10800 1 -04}
    {1933210800 -14400 0 -04}
    {1946520000 -10800 1 -04}
    {1964660400 -14400 0 -04}
    {1977969600 -10800 1 -04}
    {1996110000 -14400 0 -04}
    {2009419200 -10800 1 -04}
    {2027559600 -14400 0 -04}
    {2040868800 -10800 1 -04}
    {2059614000 -14400 0 -04}
    {2072318400 -10800 1 -04}
    {2091063600 -14400 0 -04}
    {2104372800 -10800 1 -04}
    {2122513200 -14400 0 -04}


    {2135822400 -10800 1 -04}
    {2153962800 -14400 0 -04}
    {2167272000 -10800 1 -04}
    {2185412400 -14400 0 -04}
    {2198721600 -10800 1 -04}
    {2217466800 -14400 0 -04}
    {2230171200 -10800 1 -04}
    {2248916400 -14400 0 -04}
    {2262225600 -10800 1 -04}
    {2280366000 -14400 0 -04}
    {2293675200 -10800 1 -04}
    {2311815600 -14400 0 -04}
    {2325124800 -10800 1 -04}
    {2343265200 -14400 0 -04}
    {2356574400 -10800 1 -04}
    {2374714800 -14400 0 -04}
    {2388024000 -10800 1 -04}
    {2406769200 -14400 0 -04}
    {2419473600 -10800 1 -04}
    {2438218800 -14400 0 -04}
    {2451528000 -10800 1 -04}
    {2469668400 -14400 0 -04}
    {2482977600 -10800 1 -04}
    {2501118000 -14400 0 -04}
    {2514427200 -10800 1 -04}
    {2532567600 -14400 0 -04}
    {2545876800 -10800 1 -04}
    {2564017200 -14400 0 -04}
    {2577326400 -10800 1 -04}
    {2596071600 -14400 0 -04}
    {2609380800 -10800 1 -04}
    {2627521200 -14400 0 -04}
    {2640830400 -10800 1 -04}
    {2658970800 -14400 0 -04}
    {2672280000 -10800 1 -04}
    {2690420400 -14400 0 -04}
    {2703729600 -10800 1 -04}
    {2721870000 -14400 0 -04}
    {2735179200 -10800 1 -04}
    {2753924400 -14400 0 -04}
    {2766628800 -10800 1 -04}
    {2785374000 -14400 0 -04}
    {2798683200 -10800 1 -04}
    {2816823600 -14400 0 -04}
    {2830132800 -10800 1 -04}
    {2848273200 -14400 0 -04}
    {2861582400 -10800 1 -04}
    {2879722800 -14400 0 -04}
    {2893032000 -10800 1 -04}
    {2911172400 -14400 0 -04}
    {2924481600 -10800 1 -04}
    {2943226800 -14400 0 -04}
    {2955931200 -10800 1 -04}
    {2974676400 -14400 0 -04}
    {2987985600 -10800 1 -04}
    {3006126000 -14400 0 -04}
    {3019435200 -10800 1 -04}
    {3037575600 -14400 0 -04}
    {3050884800 -10800 1 -04}
    {3069025200 -14400 0 -04}
    {3082334400 -10800 1 -04}
    {3101079600 -14400 0 -04}
    {3113784000 -10800 1 -04}
    {3132529200 -14400 0 -04}
    {3145838400 -10800 1 -04}
    {3163978800 -14400 0 -04}
    {3177288000 -10800 1 -04}
    {3195428400 -14400 0 -04}
    {3208737600 -10800 1 -04}
    {3226878000 -14400 0 -04}
    {3240187200 -10800 1 -04}
    {3258327600 -14400 0 -04}
    {3271636800 -10800 1 -04}
    {3290382000 -14400 0 -04}
    {3303086400 -10800 1 -04}
    {3321831600 -14400 0 -04}
    {3335140800 -10800 1 -04}
    {3353281200 -14400 0 -04}
    {3366590400 -10800 1 -04}
    {3384730800 -14400 0 -04}
    {3398040000 -10800 1 -04}
    {3416180400 -14400 0 -04}
    {3429489600 -10800 1 -04}
    {3447630000 -14400 0 -04}
    {3460939200 -10800 1 -04}
    {3479684400 -14400 0 -04}
    {3492993600 -10800 1 -04}
    {3511134000 -14400 0 -04}
    {3524443200 -10800 1 -04}
    {3542583600 -14400 0 -04}
    {3555892800 -10800 1 -04}
    {3574033200 -14400 0 -04}
    {3587342400 -10800 1 -04}
    {3605482800 -14400 0 -04}
    {3618792000 -10800 1 -04}
    {3637537200 -14400 0 -04}
    {3650241600 -10800 1 -04}
    {3668986800 -14400 0 -04}
    {3682296000 -10800 1 -04}
    {3700436400 -14400 0 -04}
    {3713745600 -10800 1 -04}
    {3731886000 -14400 0 -04}
    {3745195200 -10800 1 -04}
    {3763335600 -14400 0 -04}
    {3776644800 -10800 1 -04}
    {3794785200 -14400 0 -04}
    {3808094400 -10800 1 -04}
    {3826839600 -14400 0 -04}
    {3839544000 -10800 1 -04}
    {3858289200 -14400 0 -04}
    {3871598400 -10800 1 -04}
    {3889738800 -14400 0 -04}
    {3903048000 -10800 1 -04}
    {3921188400 -14400 0 -04}
    {3934497600 -10800 1 -04}
    {3952638000 -14400 0 -04}
    {3965947200 -10800 1 -04}
    {3984692400 -14400 0 -04}
    {3997396800 -10800 1 -04}
    {4016142000 -14400 0 -04}
    {4029451200 -10800 1 -04}
    {4047591600 -14400 0 -04}
    {4060900800 -10800 1 -04}
    {4079041200 -14400 0 -04}
    {4092350400 -10800 1 -04}
}







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214


215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    {1410062400 -10800 1 -04}
    {1463281200 -14400 0 -04}
    {1471147200 -10800 1 -04}
    {1494730800 -14400 0 -04}
    {1502596800 -10800 1 -04}
    {1526180400 -14400 0 -04}
    {1534046400 -10800 1 -04}
    {1557630000 -14400 0 -04}
    {1565496000 -10800 1 -04}
    {1589079600 -14400 0 -04}
    {1596945600 -10800 1 -04}
    {1620529200 -14400 0 -04}
    {1629000000 -10800 1 -04}
    {1652583600 -14400 0 -04}
    {1660449600 -10800 1 -04}
    {1684033200 -14400 0 -04}
    {1691899200 -10800 1 -04}
    {1715482800 -14400 0 -04}
    {1723348800 -10800 1 -04}
    {1746932400 -14400 0 -04}
    {1754798400 -10800 1 -04}
    {1778382000 -14400 0 -04}
    {1786248000 -10800 1 -04}
    {1809831600 -14400 0 -04}
    {1818302400 -10800 1 -04}
    {1841886000 -14400 0 -04}
    {1849752000 -10800 1 -04}
    {1873335600 -14400 0 -04}
    {1881201600 -10800 1 -04}
    {1904785200 -14400 0 -04}
    {1912651200 -10800 1 -04}
    {1936234800 -14400 0 -04}
    {1944100800 -10800 1 -04}
    {1967684400 -14400 0 -04}
    {1976155200 -10800 1 -04}
    {1999738800 -14400 0 -04}
    {2007604800 -10800 1 -04}
    {2031188400 -14400 0 -04}
    {2039054400 -10800 1 -04}
    {2062638000 -14400 0 -04}
    {2070504000 -10800 1 -04}
    {2094087600 -14400 0 -04}
    {2101953600 -10800 1 -04}
    {2125537200 -14400 0 -04}
    {2133403200 -10800 1 -04}
    {2156986800 -14400 0 -04}
    {2165457600 -10800 1 -04}
    {2189041200 -14400 0 -04}
    {2196907200 -10800 1 -04}
    {2220490800 -14400 0 -04}
    {2228356800 -10800 1 -04}
    {2251940400 -14400 0 -04}
    {2259806400 -10800 1 -04}
    {2283390000 -14400 0 -04}
    {2291256000 -10800 1 -04}
    {2314839600 -14400 0 -04}
    {2322705600 -10800 1 -04}
    {2346894000 -14400 0 -04}
    {2354760000 -10800 1 -04}
    {2378343600 -14400 0 -04}
    {2386209600 -10800 1 -04}
    {2409793200 -14400 0 -04}
    {2417659200 -10800 1 -04}
    {2441242800 -14400 0 -04}
    {2449108800 -10800 1 -04}
    {2472692400 -14400 0 -04}
    {2480558400 -10800 1 -04}
    {2504142000 -14400 0 -04}
    {2512612800 -10800 1 -04}
    {2536196400 -14400 0 -04}
    {2544062400 -10800 1 -04}
    {2567646000 -14400 0 -04}
    {2575512000 -10800 1 -04}
    {2599095600 -14400 0 -04}
    {2606961600 -10800 1 -04}
    {2630545200 -14400 0 -04}
    {2638411200 -10800 1 -04}
    {2661994800 -14400 0 -04}
    {2669860800 -10800 1 -04}
    {2693444400 -14400 0 -04}
    {2701915200 -10800 1 -04}
    {2725498800 -14400 0 -04}
    {2733364800 -10800 1 -04}
    {2756948400 -14400 0 -04}
    {2764814400 -10800 1 -04}
    {2788398000 -14400 0 -04}
    {2796264000 -10800 1 -04}
    {2819847600 -14400 0 -04}
    {2827713600 -10800 1 -04}
    {2851297200 -14400 0 -04}
    {2859768000 -10800 1 -04}
    {2883351600 -14400 0 -04}
    {2891217600 -10800 1 -04}
    {2914801200 -14400 0 -04}
    {2922667200 -10800 1 -04}


    {2946250800 -14400 0 -04}
    {2954116800 -10800 1 -04}
    {2977700400 -14400 0 -04}
    {2985566400 -10800 1 -04}
    {3009150000 -14400 0 -04}
    {3017016000 -10800 1 -04}
    {3040599600 -14400 0 -04}
    {3049070400 -10800 1 -04}
    {3072654000 -14400 0 -04}
    {3080520000 -10800 1 -04}
    {3104103600 -14400 0 -04}
    {3111969600 -10800 1 -04}
    {3135553200 -14400 0 -04}
    {3143419200 -10800 1 -04}
    {3167002800 -14400 0 -04}
    {3174868800 -10800 1 -04}
    {3198452400 -14400 0 -04}
    {3206318400 -10800 1 -04}
    {3230506800 -14400 0 -04}
    {3238372800 -10800 1 -04}
    {3261956400 -14400 0 -04}
    {3269822400 -10800 1 -04}
    {3293406000 -14400 0 -04}
    {3301272000 -10800 1 -04}
    {3324855600 -14400 0 -04}
    {3332721600 -10800 1 -04}
    {3356305200 -14400 0 -04}
    {3364171200 -10800 1 -04}
    {3387754800 -14400 0 -04}
    {3396225600 -10800 1 -04}
    {3419809200 -14400 0 -04}
    {3427675200 -10800 1 -04}
    {3451258800 -14400 0 -04}
    {3459124800 -10800 1 -04}
    {3482708400 -14400 0 -04}
    {3490574400 -10800 1 -04}
    {3514158000 -14400 0 -04}
    {3522024000 -10800 1 -04}
    {3545607600 -14400 0 -04}
    {3553473600 -10800 1 -04}
    {3577057200 -14400 0 -04}
    {3585528000 -10800 1 -04}
    {3609111600 -14400 0 -04}
    {3616977600 -10800 1 -04}
    {3640561200 -14400 0 -04}
    {3648427200 -10800 1 -04}
    {3672010800 -14400 0 -04}
    {3679876800 -10800 1 -04}
    {3703460400 -14400 0 -04}
    {3711326400 -10800 1 -04}
    {3734910000 -14400 0 -04}
    {3743380800 -10800 1 -04}
    {3766964400 -14400 0 -04}
    {3774830400 -10800 1 -04}
    {3798414000 -14400 0 -04}
    {3806280000 -10800 1 -04}
    {3829863600 -14400 0 -04}
    {3837729600 -10800 1 -04}
    {3861313200 -14400 0 -04}
    {3869179200 -10800 1 -04}
    {3892762800 -14400 0 -04}
    {3900628800 -10800 1 -04}
    {3924212400 -14400 0 -04}
    {3932683200 -10800 1 -04}
    {3956266800 -14400 0 -04}
    {3964132800 -10800 1 -04}
    {3987716400 -14400 0 -04}
    {3995582400 -10800 1 -04}
    {4019166000 -14400 0 -04}
    {4027032000 -10800 1 -04}
    {4050615600 -14400 0 -04}
    {4058481600 -10800 1 -04}
    {4082065200 -14400 0 -04}
    {4089931200 -10800 1 -04}
}

Changes to library/tzdata/America/Sao_Paulo.

90
91
92
93
94
95
96

































































































































































97
    {1456020000 -10800 0 -03}
    {1476586800 -7200 1 -03}
    {1487469600 -10800 0 -03}
    {1508036400 -7200 1 -03}
    {1518919200 -10800 0 -03}
    {1541300400 -7200 1 -03}
    {1550368800 -10800 0 -03}

































































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    {1456020000 -10800 0 -03}
    {1476586800 -7200 1 -03}
    {1487469600 -10800 0 -03}
    {1508036400 -7200 1 -03}
    {1518919200 -10800 0 -03}
    {1541300400 -7200 1 -03}
    {1550368800 -10800 0 -03}
    {1572750000 -7200 1 -03}
    {1581818400 -10800 0 -03}
    {1604199600 -7200 1 -03}
    {1613872800 -10800 0 -03}
    {1636254000 -7200 1 -03}
    {1645322400 -10800 0 -03}
    {1667703600 -7200 1 -03}
    {1677376800 -10800 0 -03}
    {1699153200 -7200 1 -03}
    {1708221600 -10800 0 -03}
    {1730602800 -7200 1 -03}
    {1739671200 -10800 0 -03}
    {1762052400 -7200 1 -03}
    {1771725600 -10800 0 -03}
    {1793502000 -7200 1 -03}
    {1803175200 -10800 0 -03}
    {1825556400 -7200 1 -03}
    {1834624800 -10800 0 -03}
    {1857006000 -7200 1 -03}
    {1866074400 -10800 0 -03}
    {1888455600 -7200 1 -03}
    {1897524000 -10800 0 -03}
    {1919905200 -7200 1 -03}
    {1928973600 -10800 0 -03}
    {1951354800 -7200 1 -03}
    {1960423200 -10800 0 -03}
    {1983409200 -7200 1 -03}
    {1992477600 -10800 0 -03}
    {2014858800 -7200 1 -03}
    {2024532000 -10800 0 -03}
    {2046308400 -7200 1 -03}
    {2055376800 -10800 0 -03}
    {2077758000 -7200 1 -03}
    {2086826400 -10800 0 -03}
    {2109207600 -7200 1 -03}
    {2118880800 -10800 0 -03}
    {2140657200 -7200 1 -03}
    {2150330400 -10800 0 -03}
    {2172711600 -7200 1 -03}
    {2181780000 -10800 0 -03}
    {2204161200 -7200 1 -03}
    {2213229600 -10800 0 -03}
    {2235610800 -7200 1 -03}
    {2244679200 -10800 0 -03}
    {2267060400 -7200 1 -03}
    {2276128800 -10800 0 -03}
    {2298510000 -7200 1 -03}
    {2307578400 -10800 0 -03}
    {2329959600 -7200 1 -03}
    {2339632800 -10800 0 -03}
    {2362014000 -7200 1 -03}
    {2371082400 -10800 0 -03}
    {2393463600 -7200 1 -03}
    {2402532000 -10800 0 -03}
    {2424913200 -7200 1 -03}
    {2433981600 -10800 0 -03}
    {2456362800 -7200 1 -03}
    {2465431200 -10800 0 -03}
    {2487812400 -7200 1 -03}
    {2497485600 -10800 0 -03}
    {2519866800 -7200 1 -03}
    {2528935200 -10800 0 -03}
    {2551316400 -7200 1 -03}
    {2560384800 -10800 0 -03}
    {2582766000 -7200 1 -03}
    {2591834400 -10800 0 -03}
    {2614215600 -7200 1 -03}
    {2623284000 -10800 0 -03}
    {2645665200 -7200 1 -03}
    {2654733600 -10800 0 -03}
    {2677114800 -7200 1 -03}
    {2686788000 -10800 0 -03}
    {2709169200 -7200 1 -03}
    {2718237600 -10800 0 -03}
    {2740618800 -7200 1 -03}
    {2749687200 -10800 0 -03}
    {2772068400 -7200 1 -03}
    {2781136800 -10800 0 -03}
    {2803518000 -7200 1 -03}
    {2812586400 -10800 0 -03}
    {2834967600 -7200 1 -03}
    {2844036000 -10800 0 -03}
    {2867022000 -7200 1 -03}
    {2876090400 -10800 0 -03}
    {2898471600 -7200 1 -03}
    {2907540000 -10800 0 -03}
    {2929921200 -7200 1 -03}
    {2938989600 -10800 0 -03}
    {2961370800 -7200 1 -03}
    {2970439200 -10800 0 -03}
    {2992820400 -7200 1 -03}
    {3001888800 -10800 0 -03}
    {3024270000 -7200 1 -03}
    {3033943200 -10800 0 -03}
    {3056324400 -7200 1 -03}
    {3065392800 -10800 0 -03}
    {3087774000 -7200 1 -03}
    {3096842400 -10800 0 -03}
    {3119223600 -7200 1 -03}
    {3128292000 -10800 0 -03}
    {3150673200 -7200 1 -03}
    {3159741600 -10800 0 -03}
    {3182122800 -7200 1 -03}
    {3191191200 -10800 0 -03}
    {3213572400 -7200 1 -03}
    {3223245600 -10800 0 -03}
    {3245626800 -7200 1 -03}
    {3254695200 -10800 0 -03}
    {3277076400 -7200 1 -03}
    {3286144800 -10800 0 -03}
    {3308526000 -7200 1 -03}
    {3317594400 -10800 0 -03}
    {3339975600 -7200 1 -03}
    {3349044000 -10800 0 -03}
    {3371425200 -7200 1 -03}
    {3381098400 -10800 0 -03}
    {3403479600 -7200 1 -03}
    {3412548000 -10800 0 -03}
    {3434929200 -7200 1 -03}
    {3443997600 -10800 0 -03}
    {3466378800 -7200 1 -03}
    {3475447200 -10800 0 -03}
    {3497828400 -7200 1 -03}
    {3506896800 -10800 0 -03}
    {3529278000 -7200 1 -03}
    {3538346400 -10800 0 -03}
    {3560727600 -7200 1 -03}
    {3570400800 -10800 0 -03}
    {3592782000 -7200 1 -03}
    {3601850400 -10800 0 -03}
    {3624231600 -7200 1 -03}
    {3633300000 -10800 0 -03}
    {3655681200 -7200 1 -03}
    {3664749600 -10800 0 -03}
    {3687130800 -7200 1 -03}
    {3696199200 -10800 0 -03}
    {3718580400 -7200 1 -03}
    {3727648800 -10800 0 -03}
    {3750634800 -7200 1 -03}
    {3759703200 -10800 0 -03}
    {3782084400 -7200 1 -03}
    {3791152800 -10800 0 -03}
    {3813534000 -7200 1 -03}
    {3822602400 -10800 0 -03}
    {3844983600 -7200 1 -03}
    {3854052000 -10800 0 -03}
    {3876433200 -7200 1 -03}
    {3885501600 -10800 0 -03}
    {3907882800 -7200 1 -03}
    {3917556000 -10800 0 -03}
    {3939937200 -7200 1 -03}
    {3949005600 -10800 0 -03}
    {3971386800 -7200 1 -03}
    {3980455200 -10800 0 -03}
    {4002836400 -7200 1 -03}
    {4011904800 -10800 0 -03}
    {4034286000 -7200 1 -03}
    {4043354400 -10800 0 -03}
    {4065735600 -7200 1 -03}
    {4074804000 -10800 0 -03}
    {4097185200 -7200 1 -03}
}

Changes to library/tzdata/America/St_Barthelemy.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Barthelemy) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/St_Barthelemy) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/St_Kitts.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Kitts) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/St_Kitts) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/St_Lucia.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Lucia) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/St_Lucia) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/St_Thomas.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Thomas) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/St_Thomas) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/St_Vincent.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Vincent) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/St_Vincent) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Thunder_Bay.

1
2
3
4
5













































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto
}
set TZData(:America/Thunder_Bay) $TZData(:America/Toronto)














































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Thunder_Bay) {
    {-9223372036854775808 -21420 0 LMT}
    {-2366733780 -21600 0 CST}
    {-1893434400 -18000 0 EST}
    {-883594800 -18000 0 EST}
    {-880218000 -14400 1 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {18000 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {41410800 -14400 1 EDT}
    {57736800 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {94712400 -18000 0 EST}
    {126248400 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Tijuana.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Tijuana) {
    {-9223372036854775808 -28084 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1451667600 -28800 0 PST}
    {-1343062800 -25200 0 MST}
    {-1234803600 -28800 0 PST}
    {-1222963200 -25200 1 PDT}
    {-1207242000 -28800 0 PST}
    {-873820800 -25200 1 PWT}
    {-769395600 -25200 1 PPT}




|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Tijuana) {
    {-9223372036854775808 -28084 0 LMT}
    {-1514736000 -25200 0 MST}
    {-1451667600 -28800 0 PST}
    {-1343062800 -25200 0 MST}
    {-1234803600 -28800 0 PST}
    {-1222963200 -25200 1 PDT}
    {-1207242000 -28800 0 PST}
    {-873820800 -25200 1 PWT}
    {-769395600 -25200 1 PPT}

Changes to library/tzdata/America/Tortola.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Tortola) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Tortola) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Vancouver.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Vancouver) {
    {-9223372036854775808 -29548 0 LMT}
    {-2713880852 -28800 0 PST}
    {-1632060000 -25200 1 PDT}
    {-1615129200 -28800 0 PST}
    {-880207200 -25200 1 PWT}
    {-769395600 -25200 1 PPT}
    {-765385200 -28800 0 PST}
    {-747237600 -25200 1 PDT}
    {-733935600 -28800 0 PST}
    {-715788000 -25200 1 PDT}
    {-702486000 -28800 0 PST}
    {-684338400 -25200 1 PDT}
    {-671036400 -28800 0 PST}
    {-652888800 -25200 1 PDT}
    {-639586800 -28800 0 PST}
    {-620834400 -25200 1 PDT}











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Vancouver) {
    {-9223372036854775808 -29548 0 LMT}
    {-2713880852 -28800 0 PST}
    {-1632060000 -25200 1 PDT}
    {-1615129200 -28800 0 PST}
    {-880207200 -25200 1 PWT}
    {-769395600 -25200 1 PPT}
    {-765385200 -28800 0 PST}
    {-747237600 -25200 1 PDT}
    {-732726000 -28800 0 PST}
    {-715788000 -25200 1 PDT}
    {-702486000 -28800 0 PST}
    {-684338400 -25200 1 PDT}
    {-671036400 -28800 0 PST}
    {-652888800 -25200 1 PDT}
    {-639586800 -28800 0 PST}
    {-620834400 -25200 1 PDT}

Changes to library/tzdata/America/Virgin.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Virgin) $TZData(:America/Puerto_Rico)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Virgin) $TZData(:America/Port_of_Spain)

Changes to library/tzdata/America/Whitehorse.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Whitehorse) {
    {-9223372036854775808 -32412 0 LMT}
    {-2188997988 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}
    {-157734000 -32400 0 YST}
    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}
    {-121273200 -28800 0 PST}
    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}












<


<







1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Whitehorse) {
    {-9223372036854775808 -32412 0 LMT}
    {-2188997988 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}

    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}

    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}
92
93
94
95
96
97
98













































































































99

















































100
    {1489312800 -25200 1 PDT}
    {1509872400 -28800 0 PST}
    {1520762400 -25200 1 PDT}
    {1541322000 -28800 0 PST}
    {1552212000 -25200 1 PDT}
    {1572771600 -28800 0 PST}
    {1583661600 -25200 1 PDT}













































































































    {1604217600 -25200 0 MST}

















































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    {1489312800 -25200 1 PDT}
    {1509872400 -28800 0 PST}
    {1520762400 -25200 1 PDT}
    {1541322000 -28800 0 PST}
    {1552212000 -25200 1 PDT}
    {1572771600 -28800 0 PST}
    {1583661600 -25200 1 PDT}
    {1604221200 -28800 0 PST}
    {1615716000 -25200 1 PDT}
    {1636275600 -28800 0 PST}
    {1647165600 -25200 1 PDT}
    {1667725200 -28800 0 PST}
    {1678615200 -25200 1 PDT}
    {1699174800 -28800 0 PST}
    {1710064800 -25200 1 PDT}
    {1730624400 -28800 0 PST}
    {1741514400 -25200 1 PDT}
    {1762074000 -28800 0 PST}
    {1772964000 -25200 1 PDT}
    {1793523600 -28800 0 PST}
    {1805018400 -25200 1 PDT}
    {1825578000 -28800 0 PST}
    {1836468000 -25200 1 PDT}
    {1857027600 -28800 0 PST}
    {1867917600 -25200 1 PDT}
    {1888477200 -28800 0 PST}
    {1899367200 -25200 1 PDT}
    {1919926800 -28800 0 PST}
    {1930816800 -25200 1 PDT}
    {1951376400 -28800 0 PST}
    {1962871200 -25200 1 PDT}
    {1983430800 -28800 0 PST}
    {1994320800 -25200 1 PDT}
    {2014880400 -28800 0 PST}
    {2025770400 -25200 1 PDT}
    {2046330000 -28800 0 PST}
    {2057220000 -25200 1 PDT}
    {2077779600 -28800 0 PST}
    {2088669600 -25200 1 PDT}
    {2109229200 -28800 0 PST}
    {2120119200 -25200 1 PDT}
    {2140678800 -28800 0 PST}
    {2152173600 -25200 1 PDT}
    {2172733200 -28800 0 PST}
    {2183623200 -25200 1 PDT}
    {2204182800 -28800 0 PST}
    {2215072800 -25200 1 PDT}
    {2235632400 -28800 0 PST}
    {2246522400 -25200 1 PDT}
    {2267082000 -28800 0 PST}
    {2277972000 -25200 1 PDT}
    {2298531600 -28800 0 PST}
    {2309421600 -25200 1 PDT}
    {2329981200 -28800 0 PST}
    {2341476000 -25200 1 PDT}
    {2362035600 -28800 0 PST}
    {2372925600 -25200 1 PDT}
    {2393485200 -28800 0 PST}
    {2404375200 -25200 1 PDT}
    {2424934800 -28800 0 PST}
    {2435824800 -25200 1 PDT}
    {2456384400 -28800 0 PST}
    {2467274400 -25200 1 PDT}
    {2487834000 -28800 0 PST}
    {2499328800 -25200 1 PDT}
    {2519888400 -28800 0 PST}
    {2530778400 -25200 1 PDT}
    {2551338000 -28800 0 PST}
    {2562228000 -25200 1 PDT}
    {2582787600 -28800 0 PST}
    {2593677600 -25200 1 PDT}
    {2614237200 -28800 0 PST}
    {2625127200 -25200 1 PDT}
    {2645686800 -28800 0 PST}
    {2656576800 -25200 1 PDT}
    {2677136400 -28800 0 PST}
    {2688631200 -25200 1 PDT}
    {2709190800 -28800 0 PST}
    {2720080800 -25200 1 PDT}
    {2740640400 -28800 0 PST}
    {2751530400 -25200 1 PDT}
    {2772090000 -28800 0 PST}
    {2782980000 -25200 1 PDT}
    {2803539600 -28800 0 PST}
    {2814429600 -25200 1 PDT}
    {2834989200 -28800 0 PST}
    {2846484000 -25200 1 PDT}
    {2867043600 -28800 0 PST}
    {2877933600 -25200 1 PDT}
    {2898493200 -28800 0 PST}
    {2909383200 -25200 1 PDT}
    {2929942800 -28800 0 PST}
    {2940832800 -25200 1 PDT}
    {2961392400 -28800 0 PST}
    {2972282400 -25200 1 PDT}
    {2992842000 -28800 0 PST}
    {3003732000 -25200 1 PDT}
    {3024291600 -28800 0 PST}
    {3035786400 -25200 1 PDT}
    {3056346000 -28800 0 PST}
    {3067236000 -25200 1 PDT}
    {3087795600 -28800 0 PST}
    {3098685600 -25200 1 PDT}
    {3119245200 -28800 0 PST}
    {3130135200 -25200 1 PDT}
    {3150694800 -28800 0 PST}
    {3161584800 -25200 1 PDT}
    {3182144400 -28800 0 PST}
    {3193034400 -25200 1 PDT}
    {3213594000 -28800 0 PST}
    {3225088800 -25200 1 PDT}
    {3245648400 -28800 0 PST}
    {3256538400 -25200 1 PDT}
    {3277098000 -28800 0 PST}
    {3287988000 -25200 1 PDT}
    {3308547600 -28800 0 PST}
    {3319437600 -25200 1 PDT}
    {3339997200 -28800 0 PST}
    {3350887200 -25200 1 PDT}
    {3371446800 -28800 0 PST}
    {3382941600 -25200 1 PDT}
    {3403501200 -28800 0 PST}
    {3414391200 -25200 1 PDT}
    {3434950800 -28800 0 PST}
    {3445840800 -25200 1 PDT}
    {3466400400 -28800 0 PST}
    {3477290400 -25200 1 PDT}
    {3497850000 -28800 0 PST}
    {3508740000 -25200 1 PDT}
    {3529299600 -28800 0 PST}
    {3540189600 -25200 1 PDT}
    {3560749200 -28800 0 PST}
    {3572244000 -25200 1 PDT}
    {3592803600 -28800 0 PST}
    {3603693600 -25200 1 PDT}
    {3624253200 -28800 0 PST}
    {3635143200 -25200 1 PDT}
    {3655702800 -28800 0 PST}
    {3666592800 -25200 1 PDT}
    {3687152400 -28800 0 PST}
    {3698042400 -25200 1 PDT}
    {3718602000 -28800 0 PST}
    {3730096800 -25200 1 PDT}
    {3750656400 -28800 0 PST}
    {3761546400 -25200 1 PDT}
    {3782106000 -28800 0 PST}
    {3792996000 -25200 1 PDT}
    {3813555600 -28800 0 PST}
    {3824445600 -25200 1 PDT}
    {3845005200 -28800 0 PST}
    {3855895200 -25200 1 PDT}
    {3876454800 -28800 0 PST}
    {3887344800 -25200 1 PDT}
    {3907904400 -28800 0 PST}
    {3919399200 -25200 1 PDT}
    {3939958800 -28800 0 PST}
    {3950848800 -25200 1 PDT}
    {3971408400 -28800 0 PST}
    {3982298400 -25200 1 PDT}
    {4002858000 -28800 0 PST}
    {4013748000 -25200 1 PDT}
    {4034307600 -28800 0 PST}
    {4045197600 -25200 1 PDT}
    {4065757200 -28800 0 PST}
    {4076647200 -25200 1 PDT}
    {4097206800 -28800 0 PST}
}

Changes to library/tzdata/America/Yellowknife.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Yellowknife) {
    {-9223372036854775808 0 0 -00}
    {-1104537600 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {136371600 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {167821200 -21600 1 MDT}
    {183542400 -25200 0 MST}
    {199270800 -21600 1 MDT}
    {215596800 -25200 0 MST}
    {230720400 -21600 1 MDT}
    {247046400 -25200 0 MST}
    {262774800 -21600 1 MDT}
    {278496000 -25200 0 MST}
    {294224400 -21600 1 MDT}
    {309945600 -25200 0 MST}
    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}








<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<







1
2
3
4
5
6
7
8




9








10


11
12
13
14
15
16
17
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Yellowknife) {
    {-9223372036854775808 0 0 -00}
    {-1104537600 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}




    {-147891600 -18000 1 MDDT}








    {-131562000 -25200 0 MST}


    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}

Changes to library/tzdata/Antarctica/Casey.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Casey) {
    {-9223372036854775808 0 0 -00}
    {-31536000 28800 0 +08}
    {1255802400 39600 0 +11}
    {1267714800 28800 0 +08}
    {1319738400 39600 0 +11}
    {1329843600 28800 0 +08}
    {1477065600 39600 0 +11}
    {1520701200 28800 0 +08}
    {1538856000 39600 0 +11}
    {1552752000 28800 0 +08}
    {1570129200 39600 0 +11}
    {1583596800 28800 0 +08}
    {1601740860 39600 0 +11}
}











<
<
<
<
<

1
2
3
4
5
6
7
8
9
10
11





12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Casey) {
    {-9223372036854775808 0 0 -00}
    {-31536000 28800 0 +08}
    {1255802400 39600 0 +11}
    {1267714800 28800 0 +08}
    {1319738400 39600 0 +11}
    {1329843600 28800 0 +08}
    {1477065600 39600 0 +11}
    {1520701200 28800 0 +08}





}

Changes to library/tzdata/Antarctica/DumontDUrville.

1
2
3
4
5





# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Antarctica/DumontDUrville) $TZData(:Pacific/Port_Moresby)






<
<
|
|
>
>
>
>
>
1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:Antarctica/DumontDUrville) {
    {-9223372036854775808 0 0 -00}
    {-725846400 36000 0 +10}
    {-566992800 0 0 -00}
    {-415497600 36000 0 +10}
}

Changes to library/tzdata/Antarctica/Macquarie.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Macquarie) {
    {-9223372036854775808 0 0 -00}
    {-2214259200 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1669892400 39600 0 AEDT}
    {-1665388800 36000 0 AEST}
    {-1601719200 0 0 -00}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Macquarie) {
    {-9223372036854775808 0 0 -00}
    {-2214259200 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}
    {-1601719200 0 0 -00}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    {1159632000 39600 1 AEDT}
    {1174752000 36000 0 AEST}
    {1191686400 39600 1 AEDT}
    {1207411200 36000 0 AEST}
    {1223136000 39600 1 AEDT}
    {1238860800 36000 0 AEST}
    {1254585600 39600 1 AEDT}
    {1262264400 39600 1 AEDT}
    {1293800400 39600 0 AEST}
    {1301760000 36000 0 AEST}
    {1317484800 39600 1 AEDT}
    {1333209600 36000 0 AEST}
    {1349539200 39600 1 AEDT}
    {1365264000 36000 0 AEST}
    {1380988800 39600 1 AEDT}
    {1396713600 36000 0 AEST}
    {1412438400 39600 1 AEDT}
    {1428163200 36000 0 AEST}
    {1443888000 39600 1 AEDT}
    {1459612800 36000 0 AEST}
    {1475337600 39600 1 AEDT}
    {1491062400 36000 0 AEST}
    {1506787200 39600 1 AEDT}
    {1522512000 36000 0 AEST}
    {1538841600 39600 1 AEDT}
    {1554566400 36000 0 AEST}
    {1570291200 39600 1 AEDT}
    {1586016000 36000 0 AEST}
    {1601740800 39600 1 AEDT}
    {1617465600 36000 0 AEST}
    {1633190400 39600 1 AEDT}
    {1648915200 36000 0 AEST}
    {1664640000 39600 1 AEDT}
    {1680364800 36000 0 AEST}
    {1696089600 39600 1 AEDT}
    {1712419200 36000 0 AEST}
    {1728144000 39600 1 AEDT}
    {1743868800 36000 0 AEST}
    {1759593600 39600 1 AEDT}
    {1775318400 36000 0 AEST}
    {1791043200 39600 1 AEDT}
    {1806768000 36000 0 AEST}
    {1822492800 39600 1 AEDT}
    {1838217600 36000 0 AEST}
    {1853942400 39600 1 AEDT}
    {1869667200 36000 0 AEST}
    {1885996800 39600 1 AEDT}
    {1901721600 36000 0 AEST}
    {1917446400 39600 1 AEDT}
    {1933171200 36000 0 AEST}
    {1948896000 39600 1 AEDT}
    {1964620800 36000 0 AEST}
    {1980345600 39600 1 AEDT}
    {1996070400 36000 0 AEST}
    {2011795200 39600 1 AEDT}
    {2027520000 36000 0 AEST}
    {2043244800 39600 1 AEDT}
    {2058969600 36000 0 AEST}
    {2075299200 39600 1 AEDT}
    {2091024000 36000 0 AEST}
    {2106748800 39600 1 AEDT}
    {2122473600 36000 0 AEST}
    {2138198400 39600 1 AEDT}
    {2153923200 36000 0 AEST}
    {2169648000 39600 1 AEDT}
    {2185372800 36000 0 AEST}
    {2201097600 39600 1 AEDT}
    {2216822400 36000 0 AEST}
    {2233152000 39600 1 AEDT}
    {2248876800 36000 0 AEST}
    {2264601600 39600 1 AEDT}
    {2280326400 36000 0 AEST}
    {2296051200 39600 1 AEDT}
    {2311776000 36000 0 AEST}
    {2327500800 39600 1 AEDT}
    {2343225600 36000 0 AEST}
    {2358950400 39600 1 AEDT}
    {2374675200 36000 0 AEST}
    {2390400000 39600 1 AEDT}
    {2406124800 36000 0 AEST}
    {2422454400 39600 1 AEDT}
    {2438179200 36000 0 AEST}
    {2453904000 39600 1 AEDT}
    {2469628800 36000 0 AEST}
    {2485353600 39600 1 AEDT}
    {2501078400 36000 0 AEST}
    {2516803200 39600 1 AEDT}
    {2532528000 36000 0 AEST}
    {2548252800 39600 1 AEDT}
    {2563977600 36000 0 AEST}
    {2579702400 39600 1 AEDT}
    {2596032000 36000 0 AEST}
    {2611756800 39600 1 AEDT}
    {2627481600 36000 0 AEST}
    {2643206400 39600 1 AEDT}
    {2658931200 36000 0 AEST}
    {2674656000 39600 1 AEDT}
    {2690380800 36000 0 AEST}
    {2706105600 39600 1 AEDT}
    {2721830400 36000 0 AEST}
    {2737555200 39600 1 AEDT}
    {2753280000 36000 0 AEST}
    {2769609600 39600 1 AEDT}
    {2785334400 36000 0 AEST}
    {2801059200 39600 1 AEDT}
    {2816784000 36000 0 AEST}
    {2832508800 39600 1 AEDT}
    {2848233600 36000 0 AEST}
    {2863958400 39600 1 AEDT}
    {2879683200 36000 0 AEST}
    {2895408000 39600 1 AEDT}
    {2911132800 36000 0 AEST}
    {2926857600 39600 1 AEDT}
    {2942582400 36000 0 AEST}
    {2958912000 39600 1 AEDT}
    {2974636800 36000 0 AEST}
    {2990361600 39600 1 AEDT}
    {3006086400 36000 0 AEST}
    {3021811200 39600 1 AEDT}
    {3037536000 36000 0 AEST}
    {3053260800 39600 1 AEDT}
    {3068985600 36000 0 AEST}
    {3084710400 39600 1 AEDT}
    {3100435200 36000 0 AEST}
    {3116764800 39600 1 AEDT}
    {3132489600 36000 0 AEST}
    {3148214400 39600 1 AEDT}
    {3163939200 36000 0 AEST}
    {3179664000 39600 1 AEDT}
    {3195388800 36000 0 AEST}
    {3211113600 39600 1 AEDT}
    {3226838400 36000 0 AEST}
    {3242563200 39600 1 AEDT}
    {3258288000 36000 0 AEST}
    {3274012800 39600 1 AEDT}
    {3289737600 36000 0 AEST}
    {3306067200 39600 1 AEDT}
    {3321792000 36000 0 AEST}
    {3337516800 39600 1 AEDT}
    {3353241600 36000 0 AEST}
    {3368966400 39600 1 AEDT}
    {3384691200 36000 0 AEST}
    {3400416000 39600 1 AEDT}
    {3416140800 36000 0 AEST}
    {3431865600 39600 1 AEDT}
    {3447590400 36000 0 AEST}
    {3463315200 39600 1 AEDT}
    {3479644800 36000 0 AEST}
    {3495369600 39600 1 AEDT}
    {3511094400 36000 0 AEST}
    {3526819200 39600 1 AEDT}
    {3542544000 36000 0 AEST}
    {3558268800 39600 1 AEDT}
    {3573993600 36000 0 AEST}
    {3589718400 39600 1 AEDT}
    {3605443200 36000 0 AEST}
    {3621168000 39600 1 AEDT}
    {3636892800 36000 0 AEST}
    {3653222400 39600 1 AEDT}
    {3668947200 36000 0 AEST}
    {3684672000 39600 1 AEDT}
    {3700396800 36000 0 AEST}
    {3716121600 39600 1 AEDT}
    {3731846400 36000 0 AEST}
    {3747571200 39600 1 AEDT}
    {3763296000 36000 0 AEST}
    {3779020800 39600 1 AEDT}
    {3794745600 36000 0 AEST}
    {3810470400 39600 1 AEDT}
    {3826195200 36000 0 AEST}
    {3842524800 39600 1 AEDT}
    {3858249600 36000 0 AEST}
    {3873974400 39600 1 AEDT}
    {3889699200 36000 0 AEST}
    {3905424000 39600 1 AEDT}
    {3921148800 36000 0 AEST}
    {3936873600 39600 1 AEDT}
    {3952598400 36000 0 AEST}
    {3968323200 39600 1 AEDT}
    {3984048000 36000 0 AEST}
    {4000377600 39600 1 AEDT}
    {4016102400 36000 0 AEST}
    {4031827200 39600 1 AEDT}
    {4047552000 36000 0 AEST}
    {4063276800 39600 1 AEDT}
    {4079001600 36000 0 AEST}
    {4094726400 39600 1 AEDT}
}







<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

89
90
91
92
93
94
95

96


















































































































































































97
    {1159632000 39600 1 AEDT}
    {1174752000 36000 0 AEST}
    {1191686400 39600 1 AEDT}
    {1207411200 36000 0 AEST}
    {1223136000 39600 1 AEDT}
    {1238860800 36000 0 AEST}
    {1254585600 39600 1 AEDT}

    {1270310400 39600 0 +11}


















































































































































































}

Changes to library/tzdata/Antarctica/Syowa.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Riyadh)]} {
    LoadTimeZoneFile Asia/Riyadh
}
set TZData(:Antarctica/Syowa) $TZData(:Asia/Riyadh)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Antarctica/Syowa) {
    {-9223372036854775808 0 0 -00}
    {-407808000 10800 0 +03}
}

Changes to library/tzdata/Antarctica/Vostok.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Urumqi)]} {
    LoadTimeZoneFile Asia/Urumqi
}
set TZData(:Antarctica/Vostok) $TZData(:Asia/Urumqi)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Antarctica/Vostok) {
    {-9223372036854775808 0 0 -00}
    {-380073600 21600 0 +06}
}

Changes to library/tzdata/Arctic/Longyearbyen.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Berlin)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
}
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Oslo)

Changes to library/tzdata/Asia/Amman.

83
84
85
86
87
88
89
90
91


























































































































































92
    {1540504800 7200 0 EET}
    {1553810400 10800 1 EEST}
    {1571954400 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604008800 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635458400 7200 0 EET}
    {1645740000 10800 1 EEST}
    {1666908000 10800 0 +03}


























































































































































}







|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    {1540504800 7200 0 EET}
    {1553810400 10800 1 EEST}
    {1571954400 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604008800 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635458400 7200 0 EET}
    {1648764000 10800 1 EEST}
    {1666908000 7200 0 EET}
    {1680213600 10800 1 EEST}
    {1698357600 7200 0 EET}
    {1711663200 10800 1 EEST}
    {1729807200 7200 0 EET}
    {1743112800 10800 1 EEST}
    {1761861600 7200 0 EET}
    {1774562400 10800 1 EEST}
    {1793311200 7200 0 EET}
    {1806012000 10800 1 EEST}
    {1824760800 7200 0 EET}
    {1838066400 10800 1 EEST}
    {1856210400 7200 0 EET}
    {1869516000 10800 1 EEST}
    {1887660000 7200 0 EET}
    {1900965600 10800 1 EEST}
    {1919109600 7200 0 EET}
    {1932415200 10800 1 EEST}
    {1951164000 7200 0 EET}
    {1963864800 10800 1 EEST}
    {1982613600 7200 0 EET}
    {1995919200 10800 1 EEST}
    {2014063200 7200 0 EET}
    {2027368800 10800 1 EEST}
    {2045512800 7200 0 EET}
    {2058818400 10800 1 EEST}
    {2076962400 7200 0 EET}
    {2090268000 10800 1 EEST}
    {2109016800 7200 0 EET}
    {2121717600 10800 1 EEST}
    {2140466400 7200 0 EET}
    {2153167200 10800 1 EEST}
    {2171916000 7200 0 EET}
    {2185221600 10800 1 EEST}
    {2203365600 7200 0 EET}
    {2216671200 10800 1 EEST}
    {2234815200 7200 0 EET}
    {2248120800 10800 1 EEST}
    {2266264800 7200 0 EET}
    {2279570400 10800 1 EEST}
    {2298319200 7200 0 EET}
    {2311020000 10800 1 EEST}
    {2329768800 7200 0 EET}
    {2343074400 10800 1 EEST}
    {2361218400 7200 0 EET}
    {2374524000 10800 1 EEST}
    {2392668000 7200 0 EET}
    {2405973600 10800 1 EEST}
    {2424117600 7200 0 EET}
    {2437423200 10800 1 EEST}
    {2455567200 7200 0 EET}
    {2468872800 10800 1 EEST}
    {2487621600 7200 0 EET}
    {2500322400 10800 1 EEST}
    {2519071200 7200 0 EET}
    {2532376800 10800 1 EEST}
    {2550520800 7200 0 EET}
    {2563826400 10800 1 EEST}
    {2581970400 7200 0 EET}
    {2595276000 10800 1 EEST}
    {2613420000 7200 0 EET}
    {2626725600 10800 1 EEST}
    {2645474400 7200 0 EET}
    {2658175200 10800 1 EEST}
    {2676924000 7200 0 EET}
    {2689624800 10800 1 EEST}
    {2708373600 7200 0 EET}
    {2721679200 10800 1 EEST}
    {2739823200 7200 0 EET}
    {2753128800 10800 1 EEST}
    {2771272800 7200 0 EET}
    {2784578400 10800 1 EEST}
    {2802722400 7200 0 EET}
    {2816028000 10800 1 EEST}
    {2834776800 7200 0 EET}
    {2847477600 10800 1 EEST}
    {2866226400 7200 0 EET}
    {2879532000 10800 1 EEST}
    {2897676000 7200 0 EET}
    {2910981600 10800 1 EEST}
    {2929125600 7200 0 EET}
    {2942431200 10800 1 EEST}
    {2960575200 7200 0 EET}
    {2973880800 10800 1 EEST}
    {2992629600 7200 0 EET}
    {3005330400 10800 1 EEST}
    {3024079200 7200 0 EET}
    {3036780000 10800 1 EEST}
    {3055528800 7200 0 EET}
    {3068834400 10800 1 EEST}
    {3086978400 7200 0 EET}
    {3100284000 10800 1 EEST}
    {3118428000 7200 0 EET}
    {3131733600 10800 1 EEST}
    {3149877600 7200 0 EET}
    {3163183200 10800 1 EEST}
    {3181932000 7200 0 EET}
    {3194632800 10800 1 EEST}
    {3213381600 7200 0 EET}
    {3226687200 10800 1 EEST}
    {3244831200 7200 0 EET}
    {3258136800 10800 1 EEST}
    {3276280800 7200 0 EET}
    {3289586400 10800 1 EEST}
    {3307730400 7200 0 EET}
    {3321036000 10800 1 EEST}
    {3339180000 7200 0 EET}
    {3352485600 10800 1 EEST}
    {3371234400 7200 0 EET}
    {3383935200 10800 1 EEST}
    {3402684000 7200 0 EET}
    {3415989600 10800 1 EEST}
    {3434133600 7200 0 EET}
    {3447439200 10800 1 EEST}
    {3465583200 7200 0 EET}
    {3478888800 10800 1 EEST}
    {3497032800 7200 0 EET}
    {3510338400 10800 1 EEST}
    {3529087200 7200 0 EET}
    {3541788000 10800 1 EEST}
    {3560536800 7200 0 EET}
    {3573237600 10800 1 EEST}
    {3591986400 7200 0 EET}
    {3605292000 10800 1 EEST}
    {3623436000 7200 0 EET}
    {3636741600 10800 1 EEST}
    {3654885600 7200 0 EET}
    {3668191200 10800 1 EEST}
    {3686335200 7200 0 EET}
    {3699640800 10800 1 EEST}
    {3718389600 7200 0 EET}
    {3731090400 10800 1 EEST}
    {3749839200 7200 0 EET}
    {3763144800 10800 1 EEST}
    {3781288800 7200 0 EET}
    {3794594400 10800 1 EEST}
    {3812738400 7200 0 EET}
    {3826044000 10800 1 EEST}
    {3844188000 7200 0 EET}
    {3857493600 10800 1 EEST}
    {3876242400 7200 0 EET}
    {3888943200 10800 1 EEST}
    {3907692000 7200 0 EET}
    {3920392800 10800 1 EEST}
    {3939141600 7200 0 EET}
    {3952447200 10800 1 EEST}
    {3970591200 7200 0 EET}
    {3983896800 10800 1 EEST}
    {4002040800 7200 0 EET}
    {4015346400 10800 1 EEST}
    {4033490400 7200 0 EET}
    {4046796000 10800 1 EEST}
    {4065544800 7200 0 EET}
    {4078245600 10800 1 EEST}
    {4096994400 7200 0 EET}
}

Changes to library/tzdata/Asia/Brunei.

1
2
3
4
5




# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Kuching)]} {
    LoadTimeZoneFile Asia/Kuching
}
set TZData(:Asia/Brunei) $TZData(:Asia/Kuching)





<
<
|
|
>
>
>
>
1


2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit



set TZData(:Asia/Brunei) {
    {-9223372036854775808 27580 0 LMT}
    {-1383464380 27000 0 +0730}
    {-1167636600 28800 0 +08}
}

Changes to library/tzdata/Asia/Damascus.

118
119
120
121
122
123
124



























125































































































































126
    {1553810400 10800 1 EEST}
    {1571950800 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604005200 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635454800 7200 0 EET}
    {1648159200 10800 1 EEST}



























    {1666908000 10800 0 +03}































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    {1553810400 10800 1 EEST}
    {1571950800 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604005200 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635454800 7200 0 EET}
    {1648159200 10800 1 EEST}
    {1666904400 7200 0 EET}
    {1680213600 10800 1 EEST}
    {1698354000 7200 0 EET}
    {1711663200 10800 1 EEST}
    {1729803600 7200 0 EET}
    {1743112800 10800 1 EEST}
    {1761858000 7200 0 EET}
    {1774562400 10800 1 EEST}
    {1793307600 7200 0 EET}
    {1806012000 10800 1 EEST}
    {1824757200 7200 0 EET}
    {1838066400 10800 1 EEST}
    {1856206800 7200 0 EET}
    {1869516000 10800 1 EEST}
    {1887656400 7200 0 EET}
    {1900965600 10800 1 EEST}
    {1919106000 7200 0 EET}
    {1932415200 10800 1 EEST}
    {1951160400 7200 0 EET}
    {1963864800 10800 1 EEST}
    {1982610000 7200 0 EET}
    {1995314400 10800 1 EEST}
    {2014059600 7200 0 EET}
    {2027368800 10800 1 EEST}
    {2045509200 7200 0 EET}
    {2058818400 10800 1 EEST}
    {2076958800 7200 0 EET}
    {2090268000 10800 1 EEST}
    {2109013200 7200 0 EET}
    {2121717600 10800 1 EEST}
    {2140462800 7200 0 EET}
    {2153167200 10800 1 EEST}
    {2171912400 7200 0 EET}
    {2184616800 10800 1 EEST}
    {2203362000 7200 0 EET}
    {2216671200 10800 1 EEST}
    {2234811600 7200 0 EET}
    {2248120800 10800 1 EEST}
    {2266261200 7200 0 EET}
    {2279570400 10800 1 EEST}
    {2298315600 7200 0 EET}
    {2311020000 10800 1 EEST}
    {2329765200 7200 0 EET}
    {2342469600 10800 1 EEST}
    {2361214800 7200 0 EET}
    {2374524000 10800 1 EEST}
    {2392664400 7200 0 EET}
    {2405973600 10800 1 EEST}
    {2424114000 7200 0 EET}
    {2437423200 10800 1 EEST}
    {2455563600 7200 0 EET}
    {2468872800 10800 1 EEST}
    {2487618000 7200 0 EET}
    {2500322400 10800 1 EEST}
    {2519067600 7200 0 EET}
    {2531772000 10800 1 EEST}
    {2550517200 7200 0 EET}
    {2563826400 10800 1 EEST}
    {2581966800 7200 0 EET}
    {2595276000 10800 1 EEST}
    {2613416400 7200 0 EET}
    {2626725600 10800 1 EEST}
    {2645470800 7200 0 EET}
    {2658175200 10800 1 EEST}
    {2676920400 7200 0 EET}
    {2689624800 10800 1 EEST}
    {2708370000 7200 0 EET}
    {2721679200 10800 1 EEST}
    {2739819600 7200 0 EET}
    {2753128800 10800 1 EEST}
    {2771269200 7200 0 EET}
    {2784578400 10800 1 EEST}
    {2802718800 7200 0 EET}
    {2816028000 10800 1 EEST}
    {2834773200 7200 0 EET}
    {2847477600 10800 1 EEST}
    {2866222800 7200 0 EET}
    {2878927200 10800 1 EEST}
    {2897672400 7200 0 EET}
    {2910981600 10800 1 EEST}
    {2929122000 7200 0 EET}
    {2942431200 10800 1 EEST}
    {2960571600 7200 0 EET}
    {2973880800 10800 1 EEST}
    {2992626000 7200 0 EET}
    {3005330400 10800 1 EEST}
    {3024075600 7200 0 EET}
    {3036780000 10800 1 EEST}
    {3055525200 7200 0 EET}
    {3068229600 10800 1 EEST}
    {3086974800 7200 0 EET}
    {3100284000 10800 1 EEST}
    {3118424400 7200 0 EET}
    {3131733600 10800 1 EEST}
    {3149874000 7200 0 EET}
    {3163183200 10800 1 EEST}
    {3181928400 7200 0 EET}
    {3194632800 10800 1 EEST}
    {3213378000 7200 0 EET}
    {3226082400 10800 1 EEST}
    {3244827600 7200 0 EET}
    {3258136800 10800 1 EEST}
    {3276277200 7200 0 EET}
    {3289586400 10800 1 EEST}
    {3307726800 7200 0 EET}
    {3321036000 10800 1 EEST}
    {3339176400 7200 0 EET}
    {3352485600 10800 1 EEST}
    {3371230800 7200 0 EET}
    {3383935200 10800 1 EEST}
    {3402680400 7200 0 EET}
    {3415384800 10800 1 EEST}
    {3434130000 7200 0 EET}
    {3447439200 10800 1 EEST}
    {3465579600 7200 0 EET}
    {3478888800 10800 1 EEST}
    {3497029200 7200 0 EET}
    {3510338400 10800 1 EEST}
    {3529083600 7200 0 EET}
    {3541788000 10800 1 EEST}
    {3560533200 7200 0 EET}
    {3573237600 10800 1 EEST}
    {3591982800 7200 0 EET}
    {3605292000 10800 1 EEST}
    {3623432400 7200 0 EET}
    {3636741600 10800 1 EEST}
    {3654882000 7200 0 EET}
    {3668191200 10800 1 EEST}
    {3686331600 7200 0 EET}
    {3699640800 10800 1 EEST}
    {3718386000 7200 0 EET}
    {3731090400 10800 1 EEST}
    {3749835600 7200 0 EET}
    {3762540000 10800 1 EEST}
    {3781285200 7200 0 EET}
    {3794594400 10800 1 EEST}
    {3812734800 7200 0 EET}
    {3826044000 10800 1 EEST}
    {3844184400 7200 0 EET}
    {3857493600 10800 1 EEST}
    {3876238800 7200 0 EET}
    {3888943200 10800 1 EEST}
    {3907688400 7200 0 EET}
    {3920392800 10800 1 EEST}
    {3939138000 7200 0 EET}
    {3951842400 10800 1 EEST}
    {3970587600 7200 0 EET}
    {3983896800 10800 1 EEST}
    {4002037200 7200 0 EET}
    {4015346400 10800 1 EEST}
    {4033486800 7200 0 EET}
    {4046796000 10800 1 EEST}
    {4065541200 7200 0 EET}
    {4078245600 10800 1 EEST}
    {4096990800 7200 0 EET}
}

Changes to library/tzdata/Asia/Gaza.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Gaza) {
    {-9223372036854775808 8272 0 LMT}
    {-2185409872 7200 0 EEST}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 EEST}
    {-825811200 7200 0 EEST}
    {-812678400 10800 1 EEST}
    {-794188800 7200 0 EEST}
    {-779846400 10800 1 EEST}
    {-762652800 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731116800 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}





|
|
<
<

|
|
|
|
|

|







1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Gaza) {
    {-9223372036854775808 8272 0 LMT}
    {-2185409872 7200 0 EEST}
    {-933645600 10800 1 EEST}
    {-857358000 7200 0 EEST}


    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}







<
<
<
<

|







36
37
38
39
40
41
42




43
44
45
46
47
48
49
50
51
    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}




    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163




164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
    {1333058400 10800 1 EEST}
    {1348178400 7200 0 EET}
    {1364508000 10800 1 EEST}
    {1380229200 7200 0 EET}
    {1395957600 10800 1 EEST}
    {1414098000 7200 0 EET}
    {1427493600 10800 1 EEST}
    {1445551200 7200 0 EET}
    {1458946800 10800 1 EEST}
    {1477692000 7200 0 EET}
    {1490396400 10800 1 EEST}
    {1509141600 7200 0 EET}
    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553810400 10800 1 EEST}


    {1572037200 7200 0 EET}
    {1585346400 10800 1 EEST}
    {1603490400 7200 0 EET}
    {1616796000 10800 1 EEST}
    {1635458400 7200 0 EET}
    {1648332000 10800 1 EEST}
    {1666998000 7200 0 EET}
    {1679702400 10800 1 EEST}
    {1698447600 7200 0 EET}
    {1711756800 10800 1 EEST}
    {1729897200 7200 0 EET}
    {1743206400 10800 1 EEST}
    {1761346800 7200 0 EET}
    {1774656000 10800 1 EEST}
    {1792796400 7200 0 EET}
    {1806105600 10800 1 EEST}
    {1824850800 7200 0 EET}
    {1837555200 10800 1 EEST}
    {1856300400 7200 0 EET}
    {1869004800 10800 1 EEST}
    {1887750000 7200 0 EET}
    {1901059200 10800 1 EEST}
    {1919199600 7200 0 EET}
    {1932508800 10800 1 EEST}
    {1950649200 7200 0 EET}
    {1963958400 10800 1 EEST}
    {1982703600 7200 0 EET}
    {1995408000 10800 1 EEST}
    {2014153200 7200 0 EET}
    {2026857600 10800 1 EEST}
    {2045602800 7200 0 EET}
    {2058307200 10800 1 EEST}
    {2077052400 7200 0 EET}
    {2090361600 10800 1 EEST}
    {2108502000 7200 0 EET}
    {2121811200 10800 1 EEST}
    {2139951600 7200 0 EET}
    {2153260800 10800 1 EEST}
    {2172006000 7200 0 EET}
    {2184710400 10800 1 EEST}
    {2203455600 7200 0 EET}




    {2216160000 10800 1 EEST}
    {2234905200 7200 0 EET}
    {2248214400 10800 1 EEST}
    {2266354800 7200 0 EET}
    {2279664000 10800 1 EEST}
    {2297804400 7200 0 EET}
    {2311113600 10800 1 EEST}
    {2329254000 7200 0 EET}
    {2342563200 10800 1 EEST}
    {2361308400 7200 0 EET}
    {2374012800 10800 1 EEST}
    {2392758000 7200 0 EET}
    {2405462400 10800 1 EEST}
    {2424207600 7200 0 EET}
    {2437516800 10800 1 EEST}
    {2455657200 7200 0 EET}
    {2468966400 10800 1 EEST}
    {2487106800 7200 0 EET}
    {2500416000 10800 1 EEST}
    {2519161200 7200 0 EET}
    {2531865600 10800 1 EEST}
    {2550610800 7200 0 EET}
    {2563315200 10800 1 EEST}
    {2582060400 7200 0 EET}
    {2595369600 10800 1 EEST}
    {2613510000 7200 0 EET}
    {2626819200 10800 1 EEST}
    {2644959600 7200 0 EET}
    {2658268800 10800 1 EEST}
    {2676409200 7200 0 EET}
    {2689718400 10800 1 EEST}
    {2708463600 7200 0 EET}
    {2721168000 10800 1 EEST}
    {2739913200 7200 0 EET}
    {2752617600 10800 1 EEST}
    {2771362800 7200 0 EET}
    {2784672000 10800 1 EEST}
    {2802812400 7200 0 EET}
    {2816121600 10800 1 EEST}
    {2834262000 7200 0 EET}
    {2847571200 10800 1 EEST}
    {2866316400 7200 0 EET}
    {2879020800 10800 1 EEST}
    {2897766000 7200 0 EET}
    {2910470400 10800 1 EEST}
    {2929215600 7200 0 EET}
    {2941920000 10800 1 EEST}
    {2960665200 7200 0 EET}
    {2973974400 10800 1 EEST}
    {2992114800 7200 0 EET}
    {3005424000 10800 1 EEST}
    {3023564400 7200 0 EET}
    {3036873600 10800 1 EEST}
    {3055618800 7200 0 EET}
    {3068323200 10800 1 EEST}
    {3087068400 7200 0 EET}
    {3099772800 10800 1 EEST}
    {3118518000 7200 0 EET}
    {3131827200 10800 1 EEST}
    {3149967600 7200 0 EET}
    {3163276800 10800 1 EEST}
    {3181417200 7200 0 EET}
    {3194726400 10800 1 EEST}
    {3212866800 7200 0 EET}
    {3226176000 10800 1 EEST}
    {3244921200 7200 0 EET}
    {3257625600 10800 1 EEST}
    {3276370800 7200 0 EET}
    {3289075200 10800 1 EEST}
    {3307820400 7200 0 EET}
    {3321129600 10800 1 EEST}
    {3339270000 7200 0 EET}
    {3352579200 10800 1 EEST}
    {3370719600 7200 0 EET}
    {3384028800 10800 1 EEST}
    {3402774000 7200 0 EET}
    {3415478400 10800 1 EEST}
    {3434223600 7200 0 EET}
    {3446928000 10800 1 EEST}
    {3465673200 7200 0 EET}
    {3478982400 10800 1 EEST}
    {3497122800 7200 0 EET}
    {3510432000 10800 1 EEST}
    {3528572400 7200 0 EET}
    {3541881600 10800 1 EEST}
    {3560022000 7200 0 EET}
    {3573331200 10800 1 EEST}
    {3592076400 7200 0 EET}
    {3604780800 10800 1 EEST}
    {3623526000 7200 0 EET}
    {3636230400 10800 1 EEST}
    {3654975600 7200 0 EET}
    {3668284800 10800 1 EEST}
    {3686425200 7200 0 EET}
    {3699734400 10800 1 EEST}
    {3717874800 7200 0 EET}
    {3731184000 10800 1 EEST}
    {3749929200 7200 0 EET}
    {3762633600 10800 1 EEST}
    {3781378800 7200 0 EET}
    {3794083200 10800 1 EEST}
    {3812828400 7200 0 EET}
    {3825532800 10800 1 EEST}
    {3844278000 7200 0 EET}
    {3857587200 10800 1 EEST}
    {3875727600 7200 0 EET}
    {3889036800 10800 1 EEST}
    {3907177200 7200 0 EET}
    {3920486400 10800 1 EEST}
    {3939231600 7200 0 EET}
    {3951936000 10800 1 EEST}
    {3970681200 7200 0 EET}
    {3983385600 10800 1 EEST}
    {4002130800 7200 0 EET}
    {4015440000 10800 1 EEST}
    {4033580400 7200 0 EET}
    {4046889600 10800 1 EEST}
    {4065030000 7200 0 EET}
    {4078339200 10800 1 EEST}
    {4096479600 7200 0 EET}
}







|






|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182




183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256


257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    {1333058400 10800 1 EEST}
    {1348178400 7200 0 EET}
    {1364508000 10800 1 EEST}
    {1380229200 7200 0 EET}
    {1395957600 10800 1 EEST}
    {1414098000 7200 0 EET}
    {1427493600 10800 1 EEST}
    {1445547600 7200 0 EET}
    {1458946800 10800 1 EEST}
    {1477692000 7200 0 EET}
    {1490396400 10800 1 EEST}
    {1509141600 7200 0 EET}
    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553295600 10800 1 EEST}
    {1572040800 7200 0 EET}
    {1585350000 10800 1 EEST}
    {1604095200 7200 0 EET}
    {1616799600 10800 1 EEST}
    {1635544800 7200 0 EET}
    {1648249200 10800 1 EEST}
    {1666994400 7200 0 EET}
    {1679698800 10800 1 EEST}
    {1698444000 7200 0 EET}
    {1711148400 10800 1 EEST}
    {1729893600 7200 0 EET}
    {1742598000 10800 1 EEST}
    {1761343200 7200 0 EET}
    {1774652400 10800 1 EEST}
    {1793397600 7200 0 EET}
    {1806102000 10800 1 EEST}
    {1824847200 7200 0 EET}
    {1837551600 10800 1 EEST}
    {1856296800 7200 0 EET}
    {1869001200 10800 1 EEST}
    {1887746400 7200 0 EET}
    {1900450800 10800 1 EEST}
    {1919196000 7200 0 EET}
    {1931900400 10800 1 EEST}
    {1950645600 7200 0 EET}
    {1963954800 10800 1 EEST}
    {1982700000 7200 0 EET}
    {1995404400 10800 1 EEST}
    {2014149600 7200 0 EET}
    {2026854000 10800 1 EEST}
    {2045599200 7200 0 EET}
    {2058303600 10800 1 EEST}
    {2077048800 7200 0 EET}
    {2089753200 10800 1 EEST}
    {2108498400 7200 0 EET}
    {2121807600 10800 1 EEST}
    {2140552800 7200 0 EET}
    {2153257200 10800 1 EEST}
    {2172002400 7200 0 EET}
    {2184706800 10800 1 EEST}
    {2203452000 7200 0 EET}
    {2216156400 10800 1 EEST}
    {2234901600 7200 0 EET}
    {2247606000 10800 1 EEST}
    {2266351200 7200 0 EET}
    {2279055600 10800 1 EEST}
    {2297800800 7200 0 EET}
    {2311110000 10800 1 EEST}
    {2329855200 7200 0 EET}
    {2342559600 10800 1 EEST}
    {2361304800 7200 0 EET}
    {2374009200 10800 1 EEST}
    {2392754400 7200 0 EET}
    {2405458800 10800 1 EEST}
    {2424204000 7200 0 EET}
    {2436908400 10800 1 EEST}
    {2455653600 7200 0 EET}
    {2468962800 10800 1 EEST}
    {2487708000 7200 0 EET}
    {2500412400 10800 1 EEST}
    {2519157600 7200 0 EET}
    {2531862000 10800 1 EEST}
    {2550607200 7200 0 EET}
    {2563311600 10800 1 EEST}
    {2582056800 7200 0 EET}
    {2594761200 10800 1 EEST}




    {2613506400 7200 0 EET}
    {2626210800 10800 1 EEST}
    {2644956000 7200 0 EET}
    {2658265200 10800 1 EEST}
    {2677010400 7200 0 EET}
    {2689714800 10800 1 EEST}
    {2708460000 7200 0 EET}
    {2721164400 10800 1 EEST}
    {2739909600 7200 0 EET}
    {2752614000 10800 1 EEST}
    {2771359200 7200 0 EET}
    {2784063600 10800 1 EEST}
    {2802808800 7200 0 EET}
    {2815513200 10800 1 EEST}
    {2834258400 7200 0 EET}
    {2847567600 10800 1 EEST}
    {2866312800 7200 0 EET}
    {2879017200 10800 1 EEST}
    {2897762400 7200 0 EET}
    {2910466800 10800 1 EEST}
    {2929212000 7200 0 EET}
    {2941916400 10800 1 EEST}
    {2960661600 7200 0 EET}
    {2973366000 10800 1 EEST}
    {2992111200 7200 0 EET}
    {3005420400 10800 1 EEST}
    {3024165600 7200 0 EET}
    {3036870000 10800 1 EEST}
    {3055615200 7200 0 EET}
    {3068319600 10800 1 EEST}
    {3087064800 7200 0 EET}
    {3099769200 10800 1 EEST}
    {3118514400 7200 0 EET}
    {3131218800 10800 1 EEST}
    {3149964000 7200 0 EET}
    {3162668400 10800 1 EEST}
    {3181413600 7200 0 EET}
    {3194722800 10800 1 EEST}
    {3213468000 7200 0 EET}
    {3226172400 10800 1 EEST}
    {3244917600 7200 0 EET}
    {3257622000 10800 1 EEST}
    {3276367200 7200 0 EET}
    {3289071600 10800 1 EEST}
    {3307816800 7200 0 EET}
    {3320521200 10800 1 EEST}
    {3339266400 7200 0 EET}
    {3352575600 10800 1 EEST}
    {3371320800 7200 0 EET}
    {3384025200 10800 1 EEST}
    {3402770400 7200 0 EET}
    {3415474800 10800 1 EEST}
    {3434220000 7200 0 EET}
    {3446924400 10800 1 EEST}
    {3465669600 7200 0 EET}
    {3478374000 10800 1 EEST}
    {3497119200 7200 0 EET}
    {3509823600 10800 1 EEST}
    {3528568800 7200 0 EET}
    {3541878000 10800 1 EEST}
    {3560623200 7200 0 EET}
    {3573327600 10800 1 EEST}
    {3592072800 7200 0 EET}
    {3604777200 10800 1 EEST}
    {3623522400 7200 0 EET}
    {3636226800 10800 1 EEST}
    {3654972000 7200 0 EET}
    {3667676400 10800 1 EEST}
    {3686421600 7200 0 EET}
    {3699126000 10800 1 EEST}
    {3717871200 7200 0 EET}
    {3731180400 10800 1 EEST}
    {3749925600 7200 0 EET}
    {3762630000 10800 1 EEST}


    {3781375200 7200 0 EET}
    {3794079600 10800 1 EEST}
    {3812824800 7200 0 EET}
    {3825529200 10800 1 EEST}
    {3844274400 7200 0 EET}
    {3856978800 10800 1 EEST}
    {3875724000 7200 0 EET}
    {3889033200 10800 1 EEST}
    {3907778400 7200 0 EET}
    {3920482800 10800 1 EEST}
    {3939228000 7200 0 EET}
    {3951932400 10800 1 EEST}
    {3970677600 7200 0 EET}
    {3983382000 10800 1 EEST}
    {4002127200 7200 0 EET}
    {4014831600 10800 1 EEST}
    {4033576800 7200 0 EET}
    {4046281200 10800 1 EEST}
    {4065026400 7200 0 EET}
    {4078335600 10800 1 EEST}
    {4097080800 7200 0 EET}
}

Changes to library/tzdata/Asia/Hebron.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hebron) {
    {-9223372036854775808 8423 0 LMT}
    {-2185410023 7200 0 EEST}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 EEST}
    {-825811200 7200 0 EEST}
    {-812678400 10800 1 EEST}
    {-794188800 7200 0 EEST}
    {-779846400 10800 1 EEST}
    {-762652800 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731116800 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}





|
|
<
<

|
|
|
|
|

|







1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hebron) {
    {-9223372036854775808 8423 0 LMT}
    {-2185410023 7200 0 EEST}
    {-933645600 10800 1 EEST}
    {-857358000 7200 0 EEST}


    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}







<
<
<
<

|







36
37
38
39
40
41
42




43
44
45
46
47
48
49
50
51
    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}




    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162




163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    {1333058400 10800 1 EEST}
    {1348178400 7200 0 EET}
    {1364508000 10800 1 EEST}
    {1380229200 7200 0 EET}
    {1395957600 10800 1 EEST}
    {1414098000 7200 0 EET}
    {1427493600 10800 1 EEST}
    {1445551200 7200 0 EET}
    {1458946800 10800 1 EEST}
    {1477692000 7200 0 EET}
    {1490396400 10800 1 EEST}
    {1509141600 7200 0 EET}
    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553810400 10800 1 EEST}


    {1572037200 7200 0 EET}
    {1585346400 10800 1 EEST}
    {1603490400 7200 0 EET}
    {1616796000 10800 1 EEST}
    {1635458400 7200 0 EET}
    {1648332000 10800 1 EEST}
    {1666998000 7200 0 EET}
    {1679702400 10800 1 EEST}
    {1698447600 7200 0 EET}
    {1711756800 10800 1 EEST}
    {1729897200 7200 0 EET}
    {1743206400 10800 1 EEST}
    {1761346800 7200 0 EET}
    {1774656000 10800 1 EEST}
    {1792796400 7200 0 EET}
    {1806105600 10800 1 EEST}
    {1824850800 7200 0 EET}
    {1837555200 10800 1 EEST}
    {1856300400 7200 0 EET}
    {1869004800 10800 1 EEST}
    {1887750000 7200 0 EET}
    {1901059200 10800 1 EEST}
    {1919199600 7200 0 EET}
    {1932508800 10800 1 EEST}
    {1950649200 7200 0 EET}
    {1963958400 10800 1 EEST}
    {1982703600 7200 0 EET}
    {1995408000 10800 1 EEST}
    {2014153200 7200 0 EET}
    {2026857600 10800 1 EEST}
    {2045602800 7200 0 EET}
    {2058307200 10800 1 EEST}
    {2077052400 7200 0 EET}
    {2090361600 10800 1 EEST}
    {2108502000 7200 0 EET}
    {2121811200 10800 1 EEST}
    {2139951600 7200 0 EET}
    {2153260800 10800 1 EEST}
    {2172006000 7200 0 EET}
    {2184710400 10800 1 EEST}
    {2203455600 7200 0 EET}




    {2216160000 10800 1 EEST}
    {2234905200 7200 0 EET}
    {2248214400 10800 1 EEST}
    {2266354800 7200 0 EET}
    {2279664000 10800 1 EEST}
    {2297804400 7200 0 EET}
    {2311113600 10800 1 EEST}
    {2329254000 7200 0 EET}
    {2342563200 10800 1 EEST}
    {2361308400 7200 0 EET}
    {2374012800 10800 1 EEST}
    {2392758000 7200 0 EET}
    {2405462400 10800 1 EEST}
    {2424207600 7200 0 EET}
    {2437516800 10800 1 EEST}
    {2455657200 7200 0 EET}
    {2468966400 10800 1 EEST}
    {2487106800 7200 0 EET}
    {2500416000 10800 1 EEST}
    {2519161200 7200 0 EET}
    {2531865600 10800 1 EEST}
    {2550610800 7200 0 EET}
    {2563315200 10800 1 EEST}
    {2582060400 7200 0 EET}
    {2595369600 10800 1 EEST}
    {2613510000 7200 0 EET}
    {2626819200 10800 1 EEST}
    {2644959600 7200 0 EET}
    {2658268800 10800 1 EEST}
    {2676409200 7200 0 EET}
    {2689718400 10800 1 EEST}
    {2708463600 7200 0 EET}
    {2721168000 10800 1 EEST}
    {2739913200 7200 0 EET}
    {2752617600 10800 1 EEST}
    {2771362800 7200 0 EET}
    {2784672000 10800 1 EEST}
    {2802812400 7200 0 EET}
    {2816121600 10800 1 EEST}
    {2834262000 7200 0 EET}
    {2847571200 10800 1 EEST}
    {2866316400 7200 0 EET}
    {2879020800 10800 1 EEST}
    {2897766000 7200 0 EET}
    {2910470400 10800 1 EEST}
    {2929215600 7200 0 EET}
    {2941920000 10800 1 EEST}
    {2960665200 7200 0 EET}
    {2973974400 10800 1 EEST}
    {2992114800 7200 0 EET}
    {3005424000 10800 1 EEST}
    {3023564400 7200 0 EET}
    {3036873600 10800 1 EEST}
    {3055618800 7200 0 EET}
    {3068323200 10800 1 EEST}
    {3087068400 7200 0 EET}
    {3099772800 10800 1 EEST}
    {3118518000 7200 0 EET}
    {3131827200 10800 1 EEST}
    {3149967600 7200 0 EET}
    {3163276800 10800 1 EEST}
    {3181417200 7200 0 EET}
    {3194726400 10800 1 EEST}
    {3212866800 7200 0 EET}
    {3226176000 10800 1 EEST}
    {3244921200 7200 0 EET}
    {3257625600 10800 1 EEST}
    {3276370800 7200 0 EET}
    {3289075200 10800 1 EEST}
    {3307820400 7200 0 EET}
    {3321129600 10800 1 EEST}
    {3339270000 7200 0 EET}
    {3352579200 10800 1 EEST}
    {3370719600 7200 0 EET}
    {3384028800 10800 1 EEST}
    {3402774000 7200 0 EET}
    {3415478400 10800 1 EEST}
    {3434223600 7200 0 EET}
    {3446928000 10800 1 EEST}
    {3465673200 7200 0 EET}
    {3478982400 10800 1 EEST}
    {3497122800 7200 0 EET}
    {3510432000 10800 1 EEST}
    {3528572400 7200 0 EET}
    {3541881600 10800 1 EEST}
    {3560022000 7200 0 EET}
    {3573331200 10800 1 EEST}
    {3592076400 7200 0 EET}
    {3604780800 10800 1 EEST}
    {3623526000 7200 0 EET}
    {3636230400 10800 1 EEST}
    {3654975600 7200 0 EET}
    {3668284800 10800 1 EEST}
    {3686425200 7200 0 EET}
    {3699734400 10800 1 EEST}
    {3717874800 7200 0 EET}
    {3731184000 10800 1 EEST}
    {3749929200 7200 0 EET}
    {3762633600 10800 1 EEST}
    {3781378800 7200 0 EET}
    {3794083200 10800 1 EEST}
    {3812828400 7200 0 EET}
    {3825532800 10800 1 EEST}
    {3844278000 7200 0 EET}
    {3857587200 10800 1 EEST}
    {3875727600 7200 0 EET}
    {3889036800 10800 1 EEST}
    {3907177200 7200 0 EET}
    {3920486400 10800 1 EEST}
    {3939231600 7200 0 EET}
    {3951936000 10800 1 EEST}
    {3970681200 7200 0 EET}
    {3983385600 10800 1 EEST}
    {4002130800 7200 0 EET}
    {4015440000 10800 1 EEST}
    {4033580400 7200 0 EET}
    {4046889600 10800 1 EEST}
    {4065030000 7200 0 EET}
    {4078339200 10800 1 EEST}
    {4096479600 7200 0 EET}
}







|






|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181




182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255


256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    {1333058400 10800 1 EEST}
    {1348178400 7200 0 EET}
    {1364508000 10800 1 EEST}
    {1380229200 7200 0 EET}
    {1395957600 10800 1 EEST}
    {1414098000 7200 0 EET}
    {1427493600 10800 1 EEST}
    {1445547600 7200 0 EET}
    {1458946800 10800 1 EEST}
    {1477692000 7200 0 EET}
    {1490396400 10800 1 EEST}
    {1509141600 7200 0 EET}
    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553295600 10800 1 EEST}
    {1572040800 7200 0 EET}
    {1585350000 10800 1 EEST}
    {1604095200 7200 0 EET}
    {1616799600 10800 1 EEST}
    {1635544800 7200 0 EET}
    {1648249200 10800 1 EEST}
    {1666994400 7200 0 EET}
    {1679698800 10800 1 EEST}
    {1698444000 7200 0 EET}
    {1711148400 10800 1 EEST}
    {1729893600 7200 0 EET}
    {1742598000 10800 1 EEST}
    {1761343200 7200 0 EET}
    {1774652400 10800 1 EEST}
    {1793397600 7200 0 EET}
    {1806102000 10800 1 EEST}
    {1824847200 7200 0 EET}
    {1837551600 10800 1 EEST}
    {1856296800 7200 0 EET}
    {1869001200 10800 1 EEST}
    {1887746400 7200 0 EET}
    {1900450800 10800 1 EEST}
    {1919196000 7200 0 EET}
    {1931900400 10800 1 EEST}
    {1950645600 7200 0 EET}
    {1963954800 10800 1 EEST}
    {1982700000 7200 0 EET}
    {1995404400 10800 1 EEST}
    {2014149600 7200 0 EET}
    {2026854000 10800 1 EEST}
    {2045599200 7200 0 EET}
    {2058303600 10800 1 EEST}
    {2077048800 7200 0 EET}
    {2089753200 10800 1 EEST}
    {2108498400 7200 0 EET}
    {2121807600 10800 1 EEST}
    {2140552800 7200 0 EET}
    {2153257200 10800 1 EEST}
    {2172002400 7200 0 EET}
    {2184706800 10800 1 EEST}
    {2203452000 7200 0 EET}
    {2216156400 10800 1 EEST}
    {2234901600 7200 0 EET}
    {2247606000 10800 1 EEST}
    {2266351200 7200 0 EET}
    {2279055600 10800 1 EEST}
    {2297800800 7200 0 EET}
    {2311110000 10800 1 EEST}
    {2329855200 7200 0 EET}
    {2342559600 10800 1 EEST}
    {2361304800 7200 0 EET}
    {2374009200 10800 1 EEST}
    {2392754400 7200 0 EET}
    {2405458800 10800 1 EEST}
    {2424204000 7200 0 EET}
    {2436908400 10800 1 EEST}
    {2455653600 7200 0 EET}
    {2468962800 10800 1 EEST}
    {2487708000 7200 0 EET}
    {2500412400 10800 1 EEST}
    {2519157600 7200 0 EET}
    {2531862000 10800 1 EEST}
    {2550607200 7200 0 EET}
    {2563311600 10800 1 EEST}
    {2582056800 7200 0 EET}
    {2594761200 10800 1 EEST}




    {2613506400 7200 0 EET}
    {2626210800 10800 1 EEST}
    {2644956000 7200 0 EET}
    {2658265200 10800 1 EEST}
    {2677010400 7200 0 EET}
    {2689714800 10800 1 EEST}
    {2708460000 7200 0 EET}
    {2721164400 10800 1 EEST}
    {2739909600 7200 0 EET}
    {2752614000 10800 1 EEST}
    {2771359200 7200 0 EET}
    {2784063600 10800 1 EEST}
    {2802808800 7200 0 EET}
    {2815513200 10800 1 EEST}
    {2834258400 7200 0 EET}
    {2847567600 10800 1 EEST}
    {2866312800 7200 0 EET}
    {2879017200 10800 1 EEST}
    {2897762400 7200 0 EET}
    {2910466800 10800 1 EEST}
    {2929212000 7200 0 EET}
    {2941916400 10800 1 EEST}
    {2960661600 7200 0 EET}
    {2973366000 10800 1 EEST}
    {2992111200 7200 0 EET}
    {3005420400 10800 1 EEST}
    {3024165600 7200 0 EET}
    {3036870000 10800 1 EEST}
    {3055615200 7200 0 EET}
    {3068319600 10800 1 EEST}
    {3087064800 7200 0 EET}
    {3099769200 10800 1 EEST}
    {3118514400 7200 0 EET}
    {3131218800 10800 1 EEST}
    {3149964000 7200 0 EET}
    {3162668400 10800 1 EEST}
    {3181413600 7200 0 EET}
    {3194722800 10800 1 EEST}
    {3213468000 7200 0 EET}
    {3226172400 10800 1 EEST}
    {3244917600 7200 0 EET}
    {3257622000 10800 1 EEST}
    {3276367200 7200 0 EET}
    {3289071600 10800 1 EEST}
    {3307816800 7200 0 EET}
    {3320521200 10800 1 EEST}
    {3339266400 7200 0 EET}
    {3352575600 10800 1 EEST}
    {3371320800 7200 0 EET}
    {3384025200 10800 1 EEST}
    {3402770400 7200 0 EET}
    {3415474800 10800 1 EEST}
    {3434220000 7200 0 EET}
    {3446924400 10800 1 EEST}
    {3465669600 7200 0 EET}
    {3478374000 10800 1 EEST}
    {3497119200 7200 0 EET}
    {3509823600 10800 1 EEST}
    {3528568800 7200 0 EET}
    {3541878000 10800 1 EEST}
    {3560623200 7200 0 EET}
    {3573327600 10800 1 EEST}
    {3592072800 7200 0 EET}
    {3604777200 10800 1 EEST}
    {3623522400 7200 0 EET}
    {3636226800 10800 1 EEST}
    {3654972000 7200 0 EET}
    {3667676400 10800 1 EEST}
    {3686421600 7200 0 EET}
    {3699126000 10800 1 EEST}
    {3717871200 7200 0 EET}
    {3731180400 10800 1 EEST}
    {3749925600 7200 0 EET}
    {3762630000 10800 1 EEST}


    {3781375200 7200 0 EET}
    {3794079600 10800 1 EEST}
    {3812824800 7200 0 EET}
    {3825529200 10800 1 EEST}
    {3844274400 7200 0 EET}
    {3856978800 10800 1 EEST}
    {3875724000 7200 0 EET}
    {3889033200 10800 1 EEST}
    {3907778400 7200 0 EET}
    {3920482800 10800 1 EEST}
    {3939228000 7200 0 EET}
    {3951932400 10800 1 EEST}
    {3970677600 7200 0 EET}
    {3983382000 10800 1 EEST}
    {4002127200 7200 0 EET}
    {4014831600 10800 1 EEST}
    {4033576800 7200 0 EET}
    {4046281200 10800 1 EEST}
    {4065026400 7200 0 EET}
    {4078335600 10800 1 EEST}
    {4097080800 7200 0 EET}
}

Changes to library/tzdata/Asia/Ho_Chi_Minh.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ho_Chi_Minh) {
    {-9223372036854775808 25590 0 LMT}
    {-2004073590 25590 0 PLMT}
    {-1851577590 25200 0 +07}
    {-852105600 28800 0 +08}
    {-782643600 32400 0 +09}
    {-767869200 25200 0 +07}
    {-718095600 28800 0 +08}
    {-457776000 25200 0 +07}
    {-315648000 28800 0 +08}



|
|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ho_Chi_Minh) {
    {-9223372036854775808 25600 0 LMT}
    {-2004073600 25590 0 PLMT}
    {-1851577590 25200 0 +07}
    {-852105600 28800 0 +08}
    {-782643600 32400 0 +09}
    {-767869200 25200 0 +07}
    {-718095600 28800 0 +08}
    {-457776000 25200 0 +07}
    {-315648000 28800 0 +08}

Changes to library/tzdata/Asia/Hong_Kong.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hong_Kong) {
    {-9223372036854775808 27402 0 LMT}
    {-2056690800 28800 0 HKT}
    {-900910800 32400 1 HKST}
    {-891579600 30600 1 HKWT}
    {-884248200 32400 0 JST}
    {-761209200 28800 0 HKT}
    {-747907200 32400 1 HKST}
    {-728541000 28800 0 HKT}
    {-717049800 32400 1 HKST}
    {-697091400 28800 0 HKT}
    {-683785800 32400 1 HKST}
    {-668061000 28800 0 HKT}
    {-654755400 32400 1 HKST}
    {-636611400 28800 0 HKT}
    {-623305800 32400 1 HKST}
    {-605161800 28800 0 HKT}
    {-591856200 32400 1 HKST}
    {-573712200 28800 0 HKT}
    {-559801800 32400 1 HKST}
    {-541657800 28800 0 HKT}
    {-528352200 32400 1 HKST}
    {-510211800 28800 0 HKT}
    {-498112200 32400 1 HKST}
    {-478762200 28800 0 HKT}
    {-466662600 32400 1 HKST}
    {-446707800 28800 0 HKT}
    {-435213000 32400 1 HKST}




|
|
|
|
|
|
|

|

|

|

|

|

|







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hong_Kong) {
    {-9223372036854775808 27402 0 LMT}
    {-2056693002 28800 0 HKT}
    {-907389000 32400 1 HKST}
    {-891667800 28800 0 HKT}
    {-884246400 32400 0 JST}
    {-766746000 28800 0 HKT}
    {-747981000 32400 1 HKST}
    {-728544600 28800 0 HKT}
    {-717049800 32400 1 HKST}
    {-694503000 28800 0 HKT}
    {-683785800 32400 1 HKST}
    {-668064600 28800 0 HKT}
    {-654755400 32400 1 HKST}
    {-636615000 28800 0 HKT}
    {-623305800 32400 1 HKST}
    {-605165400 28800 0 HKT}
    {-591856200 32400 1 HKST}
    {-573715800 28800 0 HKT}
    {-559801800 32400 1 HKST}
    {-542352600 28800 0 HKT}
    {-528352200 32400 1 HKST}
    {-510211800 28800 0 HKT}
    {-498112200 32400 1 HKST}
    {-478762200 28800 0 HKT}
    {-466662600 32400 1 HKST}
    {-446707800 28800 0 HKT}
    {-435213000 32400 1 HKST}

Changes to library/tzdata/Asia/Jerusalem.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Jerusalem) {
    {-9223372036854775808 8454 0 LMT}
    {-2840149254 8440 0 JMT}
    {-1641003640 7200 0 IST}
    {-933638400 10800 1 IDT}
    {-923097600 7200 0 IST}
    {-919036800 10800 1 IDT}
    {-857347200 7200 0 IST}
    {-844300800 10800 1 IDT}
    {-825811200 7200 0 IST}
    {-812678400 10800 1 IDT}
    {-794188800 7200 0 IST}
    {-779846400 10800 1 IDT}
    {-762652800 7200 0 IST}
    {-748310400 10800 1 IDT}
    {-731116800 7200 0 IST}
    {-681955200 14400 1 IDDT}
    {-673228800 10800 1 IDT}
    {-667958400 7200 0 IST}
    {-652320000 10800 1 IDT}
    {-636422400 7200 0 IST}
    {-622080000 10800 1 IDT}
    {-608947200 7200 0 IST}
    {-591840000 10800 1 IDT}
    {-572486400 7200 0 IST}
    {-558576000 10800 1 IDT}
    {-542851200 7200 0 IST}
    {-527731200 10800 1 IDT}
    {-514425600 7200 0 IST}
    {-490838400 10800 1 IDT}
    {-482976000 7200 0 IST}
    {-459388800 10800 1 IDT}
    {-451526400 7200 0 IST}
    {-428544000 10800 1 IDT}
    {-418262400 7200 0 IST}
    {-400118400 10800 1 IDT}
    {-387417600 7200 0 IST}
    {142380000 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}






|
|
<
<

|
|
|
|
|

|
|
|
|
|
|
|

|





|
|
|
|
|

|
|




<
<
<
<

|







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Jerusalem) {
    {-9223372036854775808 8454 0 LMT}
    {-2840149254 8440 0 JMT}
    {-1641003640 7200 0 IST}
    {-933645600 10800 1 IDT}
    {-857358000 7200 0 IST}


    {-844300800 10800 1 IDT}
    {-825822000 7200 0 IST}
    {-812685600 10800 1 IDT}
    {-794199600 7200 0 IST}
    {-779853600 10800 1 IDT}
    {-762656400 7200 0 IST}
    {-748310400 10800 1 IDT}
    {-731127600 7200 0 IST}
    {-681962400 14400 1 IDDT}
    {-673243200 10800 1 IDT}
    {-667962000 7200 0 IST}
    {-652327200 10800 1 IDT}
    {-636426000 7200 0 IST}
    {-622087200 10800 1 IDT}
    {-608947200 7200 0 IST}
    {-591847200 10800 1 IDT}
    {-572486400 7200 0 IST}
    {-558576000 10800 1 IDT}
    {-542851200 7200 0 IST}
    {-527731200 10800 1 IDT}
    {-514425600 7200 0 IST}
    {-490845600 10800 1 IDT}
    {-482986800 7200 0 IST}
    {-459475200 10800 1 IDT}
    {-451537200 7200 0 IST}
    {-428551200 10800 1 IDT}
    {-418262400 7200 0 IST}
    {-400032000 10800 1 IDT}
    {-387428400 7200 0 IST}
    {142380000 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}




    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}

Changes to library/tzdata/Asia/Kuala_Lumpur.

1
2
3
4
5










# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Singapore)]} {
    LoadTimeZoneFile Asia/Singapore
}
set TZData(:Asia/Kuala_Lumpur) $TZData(:Asia/Singapore)











<
<
|
|
>
>
>
>
>
>
>
>
>
>
1


2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit



set TZData(:Asia/Kuala_Lumpur) {
    {-9223372036854775808 24406 0 LMT}
    {-2177477206 24925 0 SMT}
    {-2038200925 25200 0 +07}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378664200 28800 0 +08}
}

Changes to library/tzdata/Asia/Macau.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Macau) {
    {-9223372036854775808 27250 0 LMT}
    {-2056692850 28800 0 CST}
    {-884509200 32400 0 +09}
    {-873280800 36000 1 +09}
    {-855918000 32400 0 +09}
    {-841744800 36000 1 +09}
    {-828529200 32400 0 +10}
    {-765363600 28800 0 CT}
    {-747046800 32400 1 CDT}
    {-733827600 28800 0 CST}
    {-716461200 32400 1 CDT}
    {-697021200 28800 0 CST}
    {-683715600 32400 1 CDT}
    {-667990800 28800 0 CST}
    {-654771600 32400 1 CDT}
    {-636627600 28800 0 CST}
    {-623322000 32400 1 CDT}
    {-605178000 28800 0 CST}
    {-591872400 32400 1 CDT}
    {-573642000 28800 0 CST}
    {-559818000 32400 1 CDT}
    {-541674000 28800 0 CST}
    {-528368400 32400 1 CDT}
    {-510224400 28800 0 CST}
    {-498128400 32400 1 CDT}
    {-478774800 28800 0 CST}
    {-466678800 32400 1 CDT}
    {-446720400 28800 0 CST}
    {-435229200 32400 1 CDT}
    {-415258200 28800 0 CST}
    {-403158600 32400 1 CDT}
    {-383808600 28800 0 CST}
    {-371709000 32400 1 CDT}
    {-352359000 28800 0 CST}
    {-340259400 32400 1 CDT}
    {-320909400 28800 0 CST}
    {-308809800 32400 1 CDT}
    {-288855000 28800 0 CST}
    {-277360200 32400 1 CDT}
    {-257405400 28800 0 CST}
    {-245910600 32400 1 CDT}
    {-225955800 28800 0 CST}
    {-213856200 32400 1 CDT}
    {-194506200 28800 0 CST}
    {-182406600 32400 1 CDT}
    {-163056600 28800 0 CST}
    {-148537800 32400 1 CDT}
    {-132820200 28800 0 CST}
    {-117088200 32400 1 CDT}
    {-101370600 28800 0 CST}
    {-85638600 32400 1 CDT}
    {-69312600 28800 0 CST}
    {-53584200 32400 1 CDT}
    {-37863000 28800 0 CST}
    {-22134600 32400 1 CDT}
    {-6413400 28800 0 CST}
    {9315000 32400 1 CDT}
    {25036200 28800 0 CST}
    {40764600 32400 1 CDT}
    {56485800 28800 0 CST}
    {72214200 32400 1 CDT}
    {88540200 28800 0 CST}
    {104268600 32400 1 CDT}
    {119989800 28800 0 CST}
    {126041400 32400 1 CDT}
    {151439400 28800 0 CST}
    {167167800 32400 1 CDT}
    {182889000 28800 0 CST}
    {198617400 32400 1 CDT}
    {214338600 28800 0 CST}
    {295385400 32400 1 CDT}
    {309292200 28800 0 CST}






}



|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|



|
|

|










|
|
|
|
|





|
|
>
>
>
>
>
>

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Macau) {
    {-9223372036854775808 27260 0 LMT}








    {-1830412800 28800 0 CST}




























    {-277360200 32400 1 CDT}
    {-257405400 28800 0 CST}
    {-245910600 32400 1 CDT}
    {-225955800 28800 0 CST}
    {-214473600 32400 1 CDT}
    {-194506200 28800 0 CST}
    {-182406600 32400 1 CDT}
    {-163056600 28800 0 CST}
    {-150969600 32400 1 CDT}
    {-131619600 28800 0 CST}
    {-117088200 32400 1 CDT}
    {-101367000 28800 0 CST}
    {-85638600 32400 1 CDT}
    {-69312600 28800 0 CST}
    {-53584200 32400 1 CDT}
    {-37863000 28800 0 CST}
    {-22134600 32400 1 CDT}
    {-6413400 28800 0 CST}
    {9315000 32400 1 CDT}
    {25036200 28800 0 CST}
    {40764600 32400 1 CDT}
    {56485800 28800 0 CST}
    {72201600 32400 1 CDT}
    {87922800 28800 0 CST}
    {103651200 32400 1 CDT}
    {119977200 28800 0 CST}
    {135705600 32400 1 CDT}
    {151439400 28800 0 CST}
    {167167800 32400 1 CDT}
    {182889000 28800 0 CST}
    {198617400 32400 1 CDT}
    {214338600 28800 0 CST}
    {230067000 32400 1 CDT}
    {245788200 28800 0 CST}
    {261504000 32400 1 CDT}
    {277225200 28800 0 CST}
    {292953600 32400 1 CDT}
    {309279600 28800 0 CST}
    {325008000 32400 1 CDT}
    {340729200 28800 0 CST}
}

Changes to library/tzdata/Asia/Manila.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Manila) {
    {-9223372036854775808 -57360 0 LMT}
    {-3944621040 29040 0 LMT}
    {-2229321840 28800 0 PST}
    {-1046678400 32400 1 PDT}
    {-1038733200 28800 0 PST}
    {-873273600 32400 0 JST}
    {-794221200 28800 0 PST}
    {-496224000 32400 1 PDT}
    {-489315600 28800 0 PST}
    {259344000 32400 1 PDT}
    {275151600 28800 0 PST}
}





|
|
|
|
|
|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Manila) {
    {-9223372036854775808 -57360 0 LMT}
    {-3944621040 29040 0 LMT}
    {-2229321840 28800 0 +08}
    {-1046678400 32400 1 +08}
    {-1038733200 28800 0 +08}
    {-873273600 32400 0 +09}
    {-794221200 28800 0 +08}
    {-496224000 32400 1 +08}
    {-489315600 28800 0 +08}
    {259344000 32400 1 +08}
    {275151600 28800 0 +08}
}

Changes to library/tzdata/Asia/Pyongyang.

1
2
3
4
5
6
7
8
9
10
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Pyongyang) {
    {-9223372036854775808 30180 0 LMT}
    {-1948782180 30600 0 KST}
    {-1830414600 32400 0 JST}
    {-768646800 32400 0 KST}
    {1439564400 30600 0 KST}
    {1525446000 32400 0 KST}
}








|

1
2
3
4
5
6
7
8
9
10
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Pyongyang) {
    {-9223372036854775808 30180 0 LMT}
    {-1948782180 30600 0 KST}
    {-1830414600 32400 0 JST}
    {-768646800 32400 0 KST}
    {1439564400 30600 0 KST}
    {1525447800 32400 0 KST}
}

Deleted library/tzdata/Asia/Qostanay.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Qostanay) {
    {-9223372036854775808 15268 0 LMT}
    {-1441167268 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +05}
    {796165200 21600 1 +05}
    {811890000 18000 0 +05}
    {828219600 21600 1 +05}
    {846363600 18000 0 +05}
    {859669200 21600 1 +05}
    {877813200 18000 0 +05}
    {891118800 21600 1 +05}
    {909262800 18000 0 +05}
    {922568400 21600 1 +05}
    {941317200 18000 0 +05}
    {954018000 21600 1 +05}
    {972766800 18000 0 +05}
    {985467600 21600 1 +05}
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 21600 0 +06}
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































Changes to library/tzdata/Asia/Qyzylorda.

50
51
52
53
54
55
56
57
58
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 21600 0 +06}
    {1545328800 18000 0 +05}
}







<

50
51
52
53
54
55
56

57
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 21600 0 +06}

}

Changes to library/tzdata/Asia/Seoul.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Seoul) {
    {-9223372036854775808 30472 0 LMT}
    {-1948782472 30600 0 KST}
    {-1830414600 32400 0 JST}
    {-767350800 32400 0 KST}
    {-681210000 36000 1 KDT}
    {-672228000 32400 0 KST}
    {-654771600 36000 1 KDT}
    {-640864800 32400 0 KST}
    {-623408400 36000 1 KDT}
    {-609415200 32400 0 KST}
    {-588848400 36000 1 KDT}
    {-577965600 32400 0 KST}
    {-498128400 30600 0 KST}
    {-462702600 34200 1 KDT}
    {-451733400 30600 0 KST}
    {-429784200 34200 1 KDT}
    {-418296600 30600 0 KST}
    {-399544200 34200 1 KDT}
    {-387451800 30600 0 KST}







<
<
<
<
<
<
<
<







1
2
3
4
5
6
7








8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Seoul) {
    {-9223372036854775808 30472 0 LMT}
    {-1948782472 30600 0 KST}
    {-1830414600 32400 0 JST}
    {-767350800 32400 0 KST}








    {-498128400 30600 0 KST}
    {-462702600 34200 1 KDT}
    {-451733400 30600 0 KST}
    {-429784200 34200 1 KDT}
    {-418296600 30600 0 KST}
    {-399544200 34200 1 KDT}
    {-387451800 30600 0 KST}

Changes to library/tzdata/Asia/Shanghai.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Shanghai) {
    {-9223372036854775808 29143 0 LMT}
    {-2177481943 28800 0 CST}
    {-1600675200 32400 1 CDT}
    {-1585904400 28800 0 CST}
    {-933667200 32400 1 CDT}
    {-922093200 28800 0 CST}
    {-908870400 32400 1 CDT}
    {-888829200 28800 0 CST}
    {-881049600 32400 1 CDT}
    {-767869200 28800 0 CST}
    {-745833600 32400 1 CDT}
    {-733827600 28800 0 CST}
    {-716889600 32400 1 CDT}
    {-699613200 28800 0 CST}
    {-683884800 32400 1 CDT}
    {-670669200 28800 0 CST}
    {-652348800 32400 1 CDT}
    {-650016000 28800 0 CST}
    {515527200 32400 1 CDT}
    {527014800 28800 0 CST}
    {545162400 32400 1 CDT}
    {558464400 28800 0 CST}
    {577216800 32400 1 CDT}
    {589914000 28800 0 CST}
    {608666400 32400 1 CDT}
    {621968400 28800 0 CST}
    {640116000 32400 1 CDT}
    {653418000 28800 0 CST}
    {671565600 32400 1 CDT}
    {684867600 28800 0 CST}
}





|
|
|
|
<
|
|
<
<
|
|
|
|
|
<
<
|
|
<
<
|
|
|
|
<
<
<
<

1
2
3
4
5
6
7
8
9

10
11


12
13
14
15
16


17
18


19
20
21
22




23
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Shanghai) {
    {-9223372036854775808 29143 0 LMT}
    {-2177481943 28800 0 CST}
    {-933494400 32400 1 CDT}
    {-923130000 28800 0 CST}
    {-908784000 32400 1 CDT}
    {-891594000 28800 0 CST}

    {-662716800 28800 0 CST}
    {515520000 32400 1 CDT}


    {527007600 28800 0 CST}
    {545155200 32400 1 CDT}
    {558457200 28800 0 CST}
    {576604800 32400 1 CDT}
    {589906800 28800 0 CST}


    {608659200 32400 1 CDT}
    {621961200 28800 0 CST}


    {640108800 32400 1 CDT}
    {653410800 28800 0 CST}
    {671558400 32400 1 CDT}
    {684860400 28800 0 CST}




}

Changes to library/tzdata/Asia/Singapore.

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Singapore) {
    {-9223372036854775808 24925 0 LMT}
    {-2177477725 24925 0 SMT}
    {-2038200925 25200 0 +07}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378662400 28800 0 +08}
}











|

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Singapore) {
    {-9223372036854775808 24925 0 LMT}
    {-2177477725 24925 0 SMT}
    {-2038200925 25200 0 +07}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378664200 28800 0 +08}
}

Changes to library/tzdata/Asia/Tehran.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tehran) {
    {-9223372036854775808 12344 0 LMT}
    {-1704165944 12344 0 TMT}
    {-1090466744 12600 0 +0330}
    {227820600 16200 1 +0330}
    {246227400 14400 0 +04}
    {259617600 18000 1 +04}
    {271108800 14400 0 +04}
    {283982400 12600 0 +0330}
    {296598600 16200 1 +0330}
    {306531000 12600 0 +0330}
    {322432200 16200 1 +0330}
    {338499000 12600 0 +0330}
    {673216200 16200 1 +0330}
    {685481400 12600 0 +0330}
    {701209800 16200 1 +0330}
    {717103800 12600 0 +0330}





|
<
|
|
|

|







1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tehran) {
    {-9223372036854775808 12344 0 LMT}
    {-1704165944 12344 0 TMT}
    {-757394744 12600 0 +0330}

    {247177800 14400 0 +04}
    {259272000 18000 1 +04}
    {277758000 14400 0 +04}
    {283982400 12600 0 +0330}
    {290809800 16200 1 +0330}
    {306531000 12600 0 +0330}
    {322432200 16200 1 +0330}
    {338499000 12600 0 +0330}
    {673216200 16200 1 +0330}
    {685481400 12600 0 +0330}
    {701209800 16200 1 +0330}
    {717103800 12600 0 +0330}
69
70
71
72
73
74
75


























































































































































76
    {1569094200 12600 0 +0330}
    {1584736200 16200 1 +0330}
    {1600630200 12600 0 +0330}
    {1616358600 16200 1 +0330}
    {1632252600 12600 0 +0330}
    {1647894600 16200 1 +0330}
    {1663788600 12600 0 +0330}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    {1569094200 12600 0 +0330}
    {1584736200 16200 1 +0330}
    {1600630200 12600 0 +0330}
    {1616358600 16200 1 +0330}
    {1632252600 12600 0 +0330}
    {1647894600 16200 1 +0330}
    {1663788600 12600 0 +0330}
    {1679430600 16200 1 +0330}
    {1695324600 12600 0 +0330}
    {1710966600 16200 1 +0330}
    {1726860600 12600 0 +0330}
    {1742589000 16200 1 +0330}
    {1758483000 12600 0 +0330}
    {1774125000 16200 1 +0330}
    {1790019000 12600 0 +0330}
    {1805661000 16200 1 +0330}
    {1821555000 12600 0 +0330}
    {1837197000 16200 1 +0330}
    {1853091000 12600 0 +0330}
    {1868733000 16200 1 +0330}
    {1884627000 12600 0 +0330}
    {1900355400 16200 1 +0330}
    {1916249400 12600 0 +0330}
    {1931891400 16200 1 +0330}
    {1947785400 12600 0 +0330}
    {1963427400 16200 1 +0330}
    {1979321400 12600 0 +0330}
    {1994963400 16200 1 +0330}
    {2010857400 12600 0 +0330}
    {2026585800 16200 1 +0330}
    {2042479800 12600 0 +0330}
    {2058121800 16200 1 +0330}
    {2074015800 12600 0 +0330}
    {2089657800 16200 1 +0330}
    {2105551800 12600 0 +0330}
    {2121193800 16200 1 +0330}
    {2137087800 12600 0 +0330}
    {2152729800 16200 1 +0330}
    {2168623800 12600 0 +0330}
    {2184265800 16200 1 +0330}
    {2200159800 12600 0 +0330}
    {2215888200 16200 1 +0330}
    {2231782200 12600 0 +0330}
    {2247424200 16200 1 +0330}
    {2263318200 12600 0 +0330}
    {2278960200 16200 1 +0330}
    {2294854200 12600 0 +0330}
    {2310496200 16200 1 +0330}
    {2326390200 12600 0 +0330}
    {2342118600 16200 1 +0330}
    {2358012600 12600 0 +0330}
    {2373654600 16200 1 +0330}
    {2389548600 12600 0 +0330}
    {2405190600 16200 1 +0330}
    {2421084600 12600 0 +0330}
    {2436726600 16200 1 +0330}
    {2452620600 12600 0 +0330}
    {2468349000 16200 1 +0330}
    {2484243000 12600 0 +0330}
    {2499885000 16200 1 +0330}
    {2515779000 12600 0 +0330}
    {2531421000 16200 1 +0330}
    {2547315000 12600 0 +0330}
    {2562957000 16200 1 +0330}
    {2578851000 12600 0 +0330}
    {2594579400 16200 1 +0330}
    {2610473400 12600 0 +0330}
    {2626115400 16200 1 +0330}
    {2642009400 12600 0 +0330}
    {2657651400 16200 1 +0330}
    {2673545400 12600 0 +0330}
    {2689187400 16200 1 +0330}
    {2705081400 12600 0 +0330}
    {2720809800 16200 1 +0330}
    {2736703800 12600 0 +0330}
    {2752345800 16200 1 +0330}
    {2768239800 12600 0 +0330}
    {2783881800 16200 1 +0330}
    {2799775800 12600 0 +0330}
    {2815417800 16200 1 +0330}
    {2831311800 12600 0 +0330}
    {2847040200 16200 1 +0330}
    {2862934200 12600 0 +0330}
    {2878576200 16200 1 +0330}
    {2894470200 12600 0 +0330}
    {2910112200 16200 1 +0330}
    {2926006200 12600 0 +0330}
    {2941648200 16200 1 +0330}
    {2957542200 12600 0 +0330}
    {2973270600 16200 1 +0330}
    {2989164600 12600 0 +0330}
    {3004806600 16200 1 +0330}
    {3020700600 12600 0 +0330}
    {3036342600 16200 1 +0330}
    {3052236600 12600 0 +0330}
    {3067878600 16200 1 +0330}
    {3083772600 12600 0 +0330}
    {3099501000 16200 1 +0330}
    {3115395000 12600 0 +0330}
    {3131037000 16200 1 +0330}
    {3146931000 12600 0 +0330}
    {3162573000 16200 1 +0330}
    {3178467000 12600 0 +0330}
    {3194109000 16200 1 +0330}
    {3210003000 12600 0 +0330}
    {3225731400 16200 1 +0330}
    {3241625400 12600 0 +0330}
    {3257267400 16200 1 +0330}
    {3273161400 12600 0 +0330}
    {3288803400 16200 1 +0330}
    {3304697400 12600 0 +0330}
    {3320339400 16200 1 +0330}
    {3336233400 12600 0 +0330}
    {3351961800 16200 1 +0330}
    {3367855800 12600 0 +0330}
    {3383497800 16200 1 +0330}
    {3399391800 12600 0 +0330}
    {3415033800 16200 1 +0330}
    {3430927800 12600 0 +0330}
    {3446569800 16200 1 +0330}
    {3462463800 12600 0 +0330}
    {3478192200 16200 1 +0330}
    {3494086200 12600 0 +0330}
    {3509728200 16200 1 +0330}
    {3525622200 12600 0 +0330}
    {3541264200 16200 1 +0330}
    {3557158200 12600 0 +0330}
    {3572800200 16200 1 +0330}
    {3588694200 12600 0 +0330}
    {3604422600 16200 1 +0330}
    {3620316600 12600 0 +0330}
    {3635958600 16200 1 +0330}
    {3651852600 12600 0 +0330}
    {3667494600 16200 1 +0330}
    {3683388600 12600 0 +0330}
    {3699030600 16200 1 +0330}
    {3714924600 12600 0 +0330}
    {3730653000 16200 1 +0330}
    {3746547000 12600 0 +0330}
    {3762189000 16200 1 +0330}
    {3778083000 12600 0 +0330}
    {3793725000 16200 1 +0330}
    {3809619000 12600 0 +0330}
    {3825261000 16200 1 +0330}
    {3841155000 12600 0 +0330}
    {3856883400 16200 1 +0330}
    {3872777400 12600 0 +0330}
    {3888419400 16200 1 +0330}
    {3904313400 12600 0 +0330}
    {3919955400 16200 1 +0330}
    {3935849400 12600 0 +0330}
    {3951491400 16200 1 +0330}
    {3967385400 12600 0 +0330}
    {3983113800 16200 1 +0330}
    {3999007800 12600 0 +0330}
    {4014649800 16200 1 +0330}
    {4030543800 12600 0 +0330}
    {4046185800 16200 1 +0330}
    {4062079800 12600 0 +0330}
    {4077721800 16200 1 +0330}
    {4093615800 12600 0 +0330}
}

Changes to library/tzdata/Asia/Tokyo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tokyo) {
    {-9223372036854775808 33539 0 LMT}
    {-2587712400 32400 0 JST}
    {-683802000 36000 1 JDT}
    {-672310800 32400 0 JST}
    {-654771600 36000 1 JDT}
    {-640861200 32400 0 JST}
    {-620298000 36000 1 JDT}
    {-609411600 32400 0 JST}
    {-588848400 36000 1 JDT}
    {-577962000 32400 0 JST}
}






|

|

|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tokyo) {
    {-9223372036854775808 33539 0 LMT}
    {-2587712400 32400 0 JST}
    {-683802000 36000 1 JDT}
    {-672314400 32400 0 JST}
    {-654771600 36000 1 JDT}
    {-640864800 32400 0 JST}
    {-620298000 36000 1 JDT}
    {-609415200 32400 0 JST}
    {-588848400 36000 1 JDT}
    {-577965600 32400 0 JST}
}

Changes to library/tzdata/Atlantic/Azores.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    {-733359600 -7200 0 -02}
    {-717624000 -3600 1 -01}
    {-701899200 -7200 0 -02}
    {-686174400 -3600 1 -01}
    {-670449600 -7200 0 -02}
    {-654724800 -3600 1 -01}
    {-639000000 -7200 0 -02}
    {-623275200 -3600 1 -01}
    {-607550400 -7200 0 -02}
    {-591825600 -3600 1 -01}
    {-575496000 -7200 0 -02}
    {-559771200 -3600 1 -01}
    {-544046400 -7200 0 -02}
    {-528321600 -3600 1 -01}
    {-512596800 -7200 0 -02}
    {-496872000 -3600 1 -01}







<
<







62
63
64
65
66
67
68


69
70
71
72
73
74
75
    {-733359600 -7200 0 -02}
    {-717624000 -3600 1 -01}
    {-701899200 -7200 0 -02}
    {-686174400 -3600 1 -01}
    {-670449600 -7200 0 -02}
    {-654724800 -3600 1 -01}
    {-639000000 -7200 0 -02}


    {-591825600 -3600 1 -01}
    {-575496000 -7200 0 -02}
    {-559771200 -3600 1 -01}
    {-544046400 -7200 0 -02}
    {-528321600 -3600 1 -01}
    {-512596800 -7200 0 -02}
    {-496872000 -3600 1 -01}

Changes to library/tzdata/Atlantic/Bermuda.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Bermuda) {
    {-9223372036854775808 -15558 0 LMT}
    {-2524506042 -15558 0 BMT}
    {-1664307642 -11958 1 BMT}
    {-1648932042 -15558 0 BMT}
    {-1632080442 -11958 1 BMT}
    {-1618692042 -15558 0 BST}
    {-1262281242 -14400 0 AT}
    {-882727200 -10800 1 ADT}
    {-858538800 -14400 0 AST}
    {-845229600 -10800 1 ADT}
    {-825879600 -14400 0 AST}
    {-814384800 -10800 1 ADT}
    {-793825200 -14400 0 AST}
    {-782935200 -10800 1 ADT}
    {-762375600 -14400 0 AST}
    {-713988000 -10800 1 ADT}
    {-703710000 -14400 0 AST}
    {-681933600 -10800 1 ADT}
    {-672865200 -14400 0 AST}
    {-650484000 -10800 1 ADT}
    {-641415600 -14400 0 AST}
    {-618429600 -10800 1 ADT}
    {-609966000 -14400 0 AST}
    {-586980000 -10800 1 ADT}
    {-578516400 -14400 0 AST}
    {-555530400 -10800 1 ADT}
    {-546462000 -14400 0 AST}
    {-429127200 -10800 1 ADT}
    {-415825200 -14400 0 AST}
    {136360800 -10800 0 ADT}
    {152082000 -14400 0 AST}
    {167810400 -10800 1 ADT}
    {183531600 -14400 0 AST}
    {189316800 -14400 0 AST}
    {199260000 -10800 1 ADT}
    {215586000 -14400 0 AST}




<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4





5






















6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Bermuda) {
    {-9223372036854775808 -15558 0 LMT}





    {-1262281242 -14400 0 AST}






















    {136360800 -10800 0 ADT}
    {152082000 -14400 0 AST}
    {167810400 -10800 1 ADT}
    {183531600 -14400 0 AST}
    {189316800 -14400 0 AST}
    {199260000 -10800 1 ADT}
    {215586000 -14400 0 AST}

Changes to library/tzdata/Atlantic/Jan_Mayen.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Berlin)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
}
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Oslo)

Changes to library/tzdata/Atlantic/Madeira.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    {-733363200 -3600 0 -01}
    {-717627600 0 1 +00}
    {-701902800 -3600 0 -01}
    {-686178000 0 1 +00}
    {-670453200 -3600 0 -01}
    {-654728400 0 1 +00}
    {-639003600 -3600 0 -01}
    {-623278800 0 1 +00}
    {-607554000 -3600 0 -01}
    {-591829200 0 1 +00}
    {-575499600 -3600 0 -01}
    {-559774800 0 1 +00}
    {-544050000 -3600 0 -01}
    {-528325200 0 1 +00}
    {-512600400 -3600 0 -01}
    {-496875600 0 1 +00}







<
<







62
63
64
65
66
67
68


69
70
71
72
73
74
75
    {-733363200 -3600 0 -01}
    {-717627600 0 1 +00}
    {-701902800 -3600 0 -01}
    {-686178000 0 1 +00}
    {-670453200 -3600 0 -01}
    {-654728400 0 1 +00}
    {-639003600 -3600 0 -01}


    {-591829200 0 1 +00}
    {-575499600 -3600 0 -01}
    {-559774800 0 1 +00}
    {-544050000 -3600 0 -01}
    {-528325200 0 1 +00}
    {-512600400 -3600 0 -01}
    {-496875600 0 1 +00}

Changes to library/tzdata/Atlantic/Reykjavik.

1
2
3
4
5






































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan
}
set TZData(:Atlantic/Reykjavik) $TZData(:Africa/Abidjan)







































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Atlantic/Reykjavik) {
    {-9223372036854775808 -5280 0 LMT}
    {-1956609120 -3600 0 -01}
    {-1668211200 0 1 -01}
    {-1647212400 -3600 0 -01}
    {-1636675200 0 1 -01}
    {-1613430000 -3600 0 -01}
    {-1605139200 0 1 -01}
    {-1581894000 -3600 0 -01}
    {-1539561600 0 1 -01}
    {-1531350000 -3600 0 -01}
    {-968025600 0 1 -01}
    {-952293600 -3600 0 -01}
    {-942008400 0 1 -01}
    {-920239200 -3600 0 -01}
    {-909957600 0 1 -01}
    {-888789600 -3600 0 -01}
    {-877903200 0 1 -01}
    {-857944800 -3600 0 -01}
    {-846453600 0 1 -01}
    {-826495200 -3600 0 -01}
    {-815004000 0 1 -01}
    {-795045600 -3600 0 -01}
    {-783554400 0 1 -01}
    {-762991200 -3600 0 -01}
    {-752104800 0 1 -01}
    {-731541600 -3600 0 -01}
    {-717631200 0 1 -01}
    {-700092000 -3600 0 -01}
    {-686181600 0 1 -01}
    {-668642400 -3600 0 -01}
    {-654732000 0 1 -01}
    {-636588000 -3600 0 -01}
    {-623282400 0 1 -01}
    {-605743200 -3600 0 -01}
    {-591832800 0 1 -01}
    {-573688800 -3600 0 -01}
    {-559778400 0 1 -01}
    {-542239200 -3600 0 -01}
    {-528328800 0 1 -01}
    {-510789600 -3600 0 -01}
    {-496879200 0 1 -01}
    {-479340000 -3600 0 -01}
    {-465429600 0 1 -01}
    {-447890400 -3600 0 -01}
    {-433980000 0 1 -01}
    {-415836000 -3600 0 -01}
    {-401925600 0 1 -01}
    {-384386400 -3600 0 -01}
    {-370476000 0 1 -01}
    {-352936800 -3600 0 -01}
    {-339026400 0 1 -01}
    {-321487200 -3600 0 -01}
    {-307576800 0 1 -01}
    {-290037600 -3600 0 -01}
    {-276127200 0 1 -01}
    {-258588000 -3600 0 -01}
    {-244677600 0 1 -01}
    {-226533600 -3600 0 -01}
    {-212623200 0 1 -01}
    {-195084000 -3600 0 -01}
    {-181173600 0 1 -01}
    {-163634400 -3600 0 -01}
    {-149724000 0 1 -01}
    {-132184800 -3600 0 -01}
    {-118274400 0 1 -01}
    {-100735200 -3600 0 -01}
    {-86824800 0 1 -01}
    {-68680800 -3600 0 -01}
    {-54770400 0 0 GMT}
}

Changes to library/tzdata/Australia/Adelaide.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Adelaide) {
    {-9223372036854775808 33260 0 LMT}
    {-2364110060 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813223800 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}






|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Adelaide) {
    {-9223372036854775808 33260 0 LMT}
    {-2364110060 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}

Changes to library/tzdata/Australia/Brisbane.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Brisbane) {
    {-9223372036854775808 36728 0 LMT}
    {-2366791928 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}





|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Brisbane) {
    {-9223372036854775808 36728 0 LMT}
    {-2366791928 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}

Changes to library/tzdata/Australia/Broken_Hill.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Broken_Hill) {
    {-9223372036854775808 33948 0 LMT}
    {-2364110748 36000 0 AEST}
    {-2314951200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813223800 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}







|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Broken_Hill) {
    {-9223372036854775808 33948 0 LMT}
    {-2364110748 36000 0 AEST}
    {-2314951200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}

Changes to library/tzdata/Australia/Currie.

1
2
3
4
5














































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Australia/Hobart)]} {
    LoadTimeZoneFile Australia/Hobart
}
set TZData(:Australia/Currie) $TZData(:Australia/Hobart)















































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# created by tools/tclZIC.tcl - do not edit



set TZData(:Australia/Currie) {
    {-9223372036854775808 34528 0 LMT}
    {-2345794528 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {47138400 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}
    {152035200 39600 1 AEDT}
    {162921600 36000 0 AEST}
    {183484800 39600 1 AEDT}
    {194976000 36000 0 AEST}
    {215539200 39600 1 AEDT}
    {226425600 36000 0 AEST}
    {246988800 39600 1 AEDT}
    {257875200 36000 0 AEST}
    {278438400 39600 1 AEDT}
    {289324800 36000 0 AEST}
    {309888000 39600 1 AEDT}
    {320774400 36000 0 AEST}
    {341337600 39600 1 AEDT}
    {352224000 36000 0 AEST}
    {372787200 39600 1 AEDT}
    {386092800 36000 0 AEST}
    {404841600 39600 1 AEDT}
    {417542400 36000 0 AEST}
    {436291200 39600 1 AEDT}
    {447177600 36000 0 AEST}
    {467740800 39600 1 AEDT}
    {478627200 36000 0 AEST}
    {499190400 39600 1 AEDT}
    {510076800 36000 0 AEST}
    {530035200 39600 1 AEDT}
    {542736000 36000 0 AEST}
    {562089600 39600 1 AEDT}
    {574790400 36000 0 AEST}
    {594144000 39600 1 AEDT}
    {606240000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {637689600 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {670348800 36000 0 AEST}
    {686678400 39600 1 AEDT}
    {701798400 36000 0 AEST}
    {718128000 39600 1 AEDT}
    {733248000 36000 0 AEST}
    {749577600 39600 1 AEDT}
    {764697600 36000 0 AEST}
    {781027200 39600 1 AEDT}
    {796147200 36000 0 AEST}
    {812476800 39600 1 AEDT}
    {828201600 36000 0 AEST}
    {844531200 39600 1 AEDT}
    {859651200 36000 0 AEST}
    {875980800 39600 1 AEDT}
    {891100800 36000 0 AEST}
    {907430400 39600 1 AEDT}
    {922550400 36000 0 AEST}
    {938880000 39600 1 AEDT}
    {954000000 36000 0 AEST}
    {967305600 39600 1 AEDT}
    {985449600 36000 0 AEST}
    {1002384000 39600 1 AEDT}
    {1017504000 36000 0 AEST}
    {1033833600 39600 1 AEDT}
    {1048953600 36000 0 AEST}
    {1065283200 39600 1 AEDT}
    {1080403200 36000 0 AEST}
    {1096732800 39600 1 AEDT}
    {1111852800 36000 0 AEST}
    {1128182400 39600 1 AEDT}
    {1143907200 36000 0 AEST}
    {1159632000 39600 1 AEDT}
    {1174752000 36000 0 AEST}
    {1191686400 39600 1 AEDT}
    {1207411200 36000 0 AEST}
    {1223136000 39600 1 AEDT}
    {1238860800 36000 0 AEST}
    {1254585600 39600 1 AEDT}
    {1270310400 36000 0 AEST}
    {1286035200 39600 1 AEDT}
    {1301760000 36000 0 AEST}
    {1317484800 39600 1 AEDT}
    {1333209600 36000 0 AEST}
    {1349539200 39600 1 AEDT}
    {1365264000 36000 0 AEST}
    {1380988800 39600 1 AEDT}
    {1396713600 36000 0 AEST}
    {1412438400 39600 1 AEDT}
    {1428163200 36000 0 AEST}
    {1443888000 39600 1 AEDT}
    {1459612800 36000 0 AEST}
    {1475337600 39600 1 AEDT}
    {1491062400 36000 0 AEST}
    {1506787200 39600 1 AEDT}
    {1522512000 36000 0 AEST}
    {1538841600 39600 1 AEDT}
    {1554566400 36000 0 AEST}
    {1570291200 39600 1 AEDT}
    {1586016000 36000 0 AEST}
    {1601740800 39600 1 AEDT}
    {1617465600 36000 0 AEST}
    {1633190400 39600 1 AEDT}
    {1648915200 36000 0 AEST}
    {1664640000 39600 1 AEDT}
    {1680364800 36000 0 AEST}
    {1696089600 39600 1 AEDT}
    {1712419200 36000 0 AEST}
    {1728144000 39600 1 AEDT}
    {1743868800 36000 0 AEST}
    {1759593600 39600 1 AEDT}
    {1775318400 36000 0 AEST}
    {1791043200 39600 1 AEDT}
    {1806768000 36000 0 AEST}
    {1822492800 39600 1 AEDT}
    {1838217600 36000 0 AEST}
    {1853942400 39600 1 AEDT}
    {1869667200 36000 0 AEST}
    {1885996800 39600 1 AEDT}
    {1901721600 36000 0 AEST}
    {1917446400 39600 1 AEDT}
    {1933171200 36000 0 AEST}
    {1948896000 39600 1 AEDT}
    {1964620800 36000 0 AEST}
    {1980345600 39600 1 AEDT}
    {1996070400 36000 0 AEST}
    {2011795200 39600 1 AEDT}
    {2027520000 36000 0 AEST}
    {2043244800 39600 1 AEDT}
    {2058969600 36000 0 AEST}
    {2075299200 39600 1 AEDT}
    {2091024000 36000 0 AEST}
    {2106748800 39600 1 AEDT}
    {2122473600 36000 0 AEST}
    {2138198400 39600 1 AEDT}
    {2153923200 36000 0 AEST}
    {2169648000 39600 1 AEDT}
    {2185372800 36000 0 AEST}
    {2201097600 39600 1 AEDT}
    {2216822400 36000 0 AEST}
    {2233152000 39600 1 AEDT}
    {2248876800 36000 0 AEST}
    {2264601600 39600 1 AEDT}
    {2280326400 36000 0 AEST}
    {2296051200 39600 1 AEDT}
    {2311776000 36000 0 AEST}
    {2327500800 39600 1 AEDT}
    {2343225600 36000 0 AEST}
    {2358950400 39600 1 AEDT}
    {2374675200 36000 0 AEST}
    {2390400000 39600 1 AEDT}
    {2406124800 36000 0 AEST}
    {2422454400 39600 1 AEDT}
    {2438179200 36000 0 AEST}
    {2453904000 39600 1 AEDT}
    {2469628800 36000 0 AEST}
    {2485353600 39600 1 AEDT}
    {2501078400 36000 0 AEST}
    {2516803200 39600 1 AEDT}
    {2532528000 36000 0 AEST}
    {2548252800 39600 1 AEDT}
    {2563977600 36000 0 AEST}
    {2579702400 39600 1 AEDT}
    {2596032000 36000 0 AEST}
    {2611756800 39600 1 AEDT}
    {2627481600 36000 0 AEST}
    {2643206400 39600 1 AEDT}
    {2658931200 36000 0 AEST}
    {2674656000 39600 1 AEDT}
    {2690380800 36000 0 AEST}
    {2706105600 39600 1 AEDT}
    {2721830400 36000 0 AEST}
    {2737555200 39600 1 AEDT}
    {2753280000 36000 0 AEST}
    {2769609600 39600 1 AEDT}
    {2785334400 36000 0 AEST}
    {2801059200 39600 1 AEDT}
    {2816784000 36000 0 AEST}
    {2832508800 39600 1 AEDT}
    {2848233600 36000 0 AEST}
    {2863958400 39600 1 AEDT}
    {2879683200 36000 0 AEST}
    {2895408000 39600 1 AEDT}
    {2911132800 36000 0 AEST}
    {2926857600 39600 1 AEDT}
    {2942582400 36000 0 AEST}
    {2958912000 39600 1 AEDT}
    {2974636800 36000 0 AEST}
    {2990361600 39600 1 AEDT}
    {3006086400 36000 0 AEST}
    {3021811200 39600 1 AEDT}
    {3037536000 36000 0 AEST}
    {3053260800 39600 1 AEDT}
    {3068985600 36000 0 AEST}
    {3084710400 39600 1 AEDT}
    {3100435200 36000 0 AEST}
    {3116764800 39600 1 AEDT}
    {3132489600 36000 0 AEST}
    {3148214400 39600 1 AEDT}
    {3163939200 36000 0 AEST}
    {3179664000 39600 1 AEDT}
    {3195388800 36000 0 AEST}
    {3211113600 39600 1 AEDT}
    {3226838400 36000 0 AEST}
    {3242563200 39600 1 AEDT}
    {3258288000 36000 0 AEST}
    {3274012800 39600 1 AEDT}
    {3289737600 36000 0 AEST}
    {3306067200 39600 1 AEDT}
    {3321792000 36000 0 AEST}
    {3337516800 39600 1 AEDT}
    {3353241600 36000 0 AEST}
    {3368966400 39600 1 AEDT}
    {3384691200 36000 0 AEST}
    {3400416000 39600 1 AEDT}
    {3416140800 36000 0 AEST}
    {3431865600 39600 1 AEDT}
    {3447590400 36000 0 AEST}
    {3463315200 39600 1 AEDT}
    {3479644800 36000 0 AEST}
    {3495369600 39600 1 AEDT}
    {3511094400 36000 0 AEST}
    {3526819200 39600 1 AEDT}
    {3542544000 36000 0 AEST}
    {3558268800 39600 1 AEDT}
    {3573993600 36000 0 AEST}
    {3589718400 39600 1 AEDT}
    {3605443200 36000 0 AEST}
    {3621168000 39600 1 AEDT}
    {3636892800 36000 0 AEST}
    {3653222400 39600 1 AEDT}
    {3668947200 36000 0 AEST}
    {3684672000 39600 1 AEDT}
    {3700396800 36000 0 AEST}
    {3716121600 39600 1 AEDT}
    {3731846400 36000 0 AEST}
    {3747571200 39600 1 AEDT}
    {3763296000 36000 0 AEST}
    {3779020800 39600 1 AEDT}
    {3794745600 36000 0 AEST}
    {3810470400 39600 1 AEDT}
    {3826195200 36000 0 AEST}
    {3842524800 39600 1 AEDT}
    {3858249600 36000 0 AEST}
    {3873974400 39600 1 AEDT}
    {3889699200 36000 0 AEST}
    {3905424000 39600 1 AEDT}
    {3921148800 36000 0 AEST}
    {3936873600 39600 1 AEDT}
    {3952598400 36000 0 AEST}
    {3968323200 39600 1 AEDT}
    {3984048000 36000 0 AEST}
    {4000377600 39600 1 AEDT}
    {4016102400 36000 0 AEST}
    {4031827200 39600 1 AEDT}
    {4047552000 36000 0 AEST}
    {4063276800 39600 1 AEDT}
    {4079001600 36000 0 AEST}
    {4094726400 39600 1 AEDT}
}

Changes to library/tzdata/Australia/Darwin.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Darwin) {
    {-9223372036854775808 31400 0 LMT}
    {-2364108200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813223800 34200 0 ACST}
}






|
|

|

|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Darwin) {
    {-9223372036854775808 31400 0 LMT}
    {-2364108200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
}

Changes to library/tzdata/Australia/Eucla.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Eucla) {
    {-9223372036854775808 30928 0 LMT}
    {-2337928528 31500 0 +0945}
    {-1672555500 35100 1 +0945}
    {-1665384300 31500 0 +0945}
    {-883637100 35100 1 +0945}
    {-876120300 31500 0 +0945}
    {-860395500 35100 1 +0945}
    {-844670700 31500 0 +0945}
    {-836473500 35100 0 +0945}
    {152039700 35100 1 +0945}
    {162926100 31500 0 +0945}
    {436295700 35100 1 +0945}
    {447182100 31500 0 +0945}
    {690311700 35100 1 +0945}
    {699383700 31500 0 +0945}





|
|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Eucla) {
    {-9223372036854775808 30928 0 LMT}
    {-2337928528 31500 0 +0945}
    {-1672562640 35100 1 +0945}
    {-1665387900 31500 0 +0945}
    {-883637100 35100 1 +0945}
    {-876123900 31500 0 +0945}
    {-860395500 35100 1 +0945}
    {-844674300 31500 0 +0945}
    {-836473500 35100 0 +0945}
    {152039700 35100 1 +0945}
    {162926100 31500 0 +0945}
    {436295700 35100 1 +0945}
    {447182100 31500 0 +0945}
    {690311700 35100 1 +0945}
    {699383700 31500 0 +0945}

Changes to library/tzdata/Australia/Hobart.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Hobart) {
    {-9223372036854775808 35356 0 LMT}
    {-2345795356 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-1646640000 39600 1 AEDT}
    {-1635753600 36000 0 AEST}
    {-1615190400 39600 1 AEDT}
    {-1604304000 36000 0 AEST}
    {-1583920800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813225600 36000 0 AEST}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}
    {5673600 36000 0 AEST}






<
<
<
|
|
<

|

|

|







1
2
3
4
5
6



7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Hobart) {
    {-9223372036854775808 35356 0 LMT}
    {-2345795356 36000 0 AEST}
    {-1680508800 39600 1 AEDT}



    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}

    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}
    {5673600 36000 0 AEST}

Changes to library/tzdata/Australia/Lindeman.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Lindeman) {
    {-9223372036854775808 35756 0 LMT}
    {-2366790956 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}





|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Lindeman) {
    {-9223372036854775808 35756 0 LMT}
    {-2366790956 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}

Changes to library/tzdata/Australia/Melbourne.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Melbourne) {
    {-9223372036854775808 34792 0 LMT}
    {-2364111592 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}





|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Melbourne) {
    {-9223372036854775808 34792 0 LMT}
    {-2364111592 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}

Changes to library/tzdata/Australia/Perth.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Perth) {
    {-9223372036854775808 27804 0 LMT}
    {-2337925404 28800 0 AWST}
    {-1672552800 32400 1 AWDT}
    {-1665381600 28800 0 AWST}
    {-883634400 32400 1 AWDT}
    {-876117600 28800 0 AWST}
    {-860392800 32400 1 AWDT}
    {-844668000 28800 0 AWST}
    {-836470800 32400 0 AWST}
    {152042400 32400 1 AWDT}
    {162928800 28800 0 AWST}
    {436298400 32400 1 AWDT}
    {447184800 28800 0 AWST}
    {690314400 32400 1 AWDT}
    {699386400 28800 0 AWST}





|
|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Perth) {
    {-9223372036854775808 27804 0 LMT}
    {-2337925404 28800 0 AWST}
    {-1672559940 32400 1 AWDT}
    {-1665385200 28800 0 AWST}
    {-883634400 32400 1 AWDT}
    {-876121200 28800 0 AWST}
    {-860392800 32400 1 AWDT}
    {-844671600 28800 0 AWST}
    {-836470800 32400 0 AWST}
    {152042400 32400 1 AWDT}
    {162928800 28800 0 AWST}
    {436298400 32400 1 AWDT}
    {447184800 28800 0 AWST}
    {690314400 32400 1 AWDT}
    {699386400 28800 0 AWST}

Changes to library/tzdata/Australia/Sydney.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Sydney) {
    {-9223372036854775808 36292 0 LMT}
    {-2364113092 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}





|
|

|

|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Sydney) {
    {-9223372036854775808 36292 0 LMT}
    {-2364113092 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}

Added library/tzdata/Canada/East-Saskatchewan.











>
>
>
>
>
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Regina)]} {
    LoadTimeZoneFile America/Regina
}
set TZData(:Canada/East-Saskatchewan) $TZData(:America/Regina)

Changes to library/tzdata/Etc/UCT.

1
2
3
4
5


# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Etc/UTC)]} {
    LoadTimeZoneFile Etc/UTC
}
set TZData(:Etc/UCT) $TZData(:Etc/UTC)



<
<
|
|
>
>
1


2
3
4
5
# created by tools/tclZIC.tcl - do not edit



set TZData(:Etc/UCT) {
    {-9223372036854775808 0 0 UCT}
}

Changes to library/tzdata/Europe/Amsterdam.

1
2
3


















































































































































































































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {
    LoadTimeZoneFile Europe/Brussels


















































































































































































































































































































}
set TZData(:Europe/Amsterdam) $TZData(:Europe/Brussels)

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Amsterdam) {
    {-9223372036854775808 1172 0 LMT}
    {-4260212372 1172 0 AMT}
    {-1693700372 4772 1 NST}
    {-1680484772 1172 0 AMT}
    {-1663453172 4772 1 NST}
    {-1650147572 1172 0 AMT}
    {-1633213172 4772 1 NST}
    {-1617488372 1172 0 AMT}
    {-1601158772 4772 1 NST}
    {-1586038772 1172 0 AMT}
    {-1569709172 4772 1 NST}
    {-1554589172 1172 0 AMT}
    {-1538259572 4772 1 NST}
    {-1523139572 1172 0 AMT}
    {-1507501172 4772 1 NST}
    {-1490566772 1172 0 AMT}
    {-1470176372 4772 1 NST}
    {-1459117172 1172 0 AMT}
    {-1443997172 4772 1 NST}
    {-1427667572 1172 0 AMT}
    {-1406672372 4772 1 NST}
    {-1396217972 1172 0 AMT}
    {-1376950772 4772 1 NST}
    {-1364768372 1172 0 AMT}
    {-1345414772 4772 1 NST}
    {-1333318772 1172 0 AMT}
    {-1313792372 4772 1 NST}
    {-1301264372 1172 0 AMT}
    {-1282256372 4772 1 NST}
    {-1269814772 1172 0 AMT}
    {-1250720372 4772 1 NST}
    {-1238365172 1172 0 AMT}
    {-1219184372 4772 1 NST}
    {-1206915572 1172 0 AMT}
    {-1186957172 4772 1 NST}
    {-1175465972 1172 0 AMT}
    {-1156025972 4772 1 NST}
    {-1143411572 1172 0 AMT}
    {-1124489972 4772 1 NST}
    {-1111961972 1172 0 AMT}
    {-1092953972 4772 1 NST}
    {-1080512372 1172 0 AMT}
    {-1061331572 4772 1 NST}
    {-1049062772 1172 0 AMT}
    {-1029190772 4772 1 NST}
    {-1025741972 4800 0 +0120}
    {-1017613200 1200 0 +0020}
    {-998259600 4800 1 +0120}
    {-986163600 1200 0 +0020}
    {-966723600 4800 1 +0120}
    {-954109200 1200 0 +0020}
    {-935022000 7200 0 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-766623600 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Brussels.

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Brussels) {
    {-9223372036854775808 1050 0 LMT}
    {-2840141850 1050 0 BMT}
    {-2450995200 0 0 WET}
    {-1740355200 3600 0 CET}
    {-1693702800 7200 0 CEST}
    {-1680483600 3600 0 CET}
    {-1663455600 7200 1 CEST}
    {-1650150000 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}





|







1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Brussels) {
    {-9223372036854775808 1050 0 LMT}
    {-2840141850 1050 0 BMT}
    {-2450953050 0 0 WET}
    {-1740355200 3600 0 CET}
    {-1693702800 7200 0 CEST}
    {-1680483600 3600 0 CET}
    {-1663455600 7200 1 CEST}
    {-1650150000 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}

Changes to library/tzdata/Europe/Budapest.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Budapest) {
    {-9223372036854775808 4580 0 LMT}
    {-2498260580 3600 0 CET}
    {-1693706400 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {-1663455600 7200 1 CEST}
    {-1650150000 3600 0 CET}
    {-1640998800 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}
    {-1600470000 7200 1 CEST}
    {-1587250800 3600 0 CET}
    {-1569711600 7200 1 CEST}
    {-1555196400 3600 0 CET}
    {-906775200 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-788922000 3600 0 CET}
    {-778471200 7200 1 CEST}
    {-762656400 3600 0 CET}
    {-749689200 7200 1 CEST}
    {-733276800 3600 0 CET}
    {-717634800 7200 1 CEST}
    {-701910000 3600 0 CET}
    {-686185200 7200 1 CEST}
    {-670460400 3600 0 CET}
    {-654130800 7200 1 CEST}
    {-639010800 3600 0 CET}


    {-492656400 7200 1 CEST}
    {-481168800 3600 0 CET}
    {-461199600 7200 1 CEST}
    {-449708400 3600 0 CET}
    {-428540400 7200 1 CEST}
    {-418258800 3600 0 CET}
    {-397090800 7200 1 CEST}
    {-386809200 3600 0 CET}
    {323823600 7200 1 CEST}
    {338943600 3600 0 CET}
    {354668400 7200 1 CEST}
    {370393200 3600 0 CET}
    {386118000 7200 1 CEST}
    {401842800 3600 0 CET}
    {417567600 7200 1 CEST}
    {433292400 3600 0 CET}
    {441759600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}




|





|

|
|
<
|
<







|

|






>
>


|
|
|
|
|

|
|
|
|
|
|
|
<
|







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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Budapest) {
    {-9223372036854775808 4580 0 LMT}
    {-2500938980 3600 0 CET}
    {-1693706400 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {-1663455600 7200 1 CEST}
    {-1650150000 3600 0 CET}
    {-1640998800 3600 0 CET}
    {-1633212000 7200 1 CEST}
    {-1618700400 3600 0 CET}
    {-1600466400 7200 1 CEST}
    {-1581202800 3600 0 CET}

    {-906771600 3600 0 CET}

    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-788922000 3600 0 CET}
    {-778471200 7200 1 CEST}
    {-762660000 3600 0 CET}
    {-749689200 7200 1 CEST}
    {-733359600 3600 0 CET}
    {-717634800 7200 1 CEST}
    {-701910000 3600 0 CET}
    {-686185200 7200 1 CEST}
    {-670460400 3600 0 CET}
    {-654130800 7200 1 CEST}
    {-639010800 3600 0 CET}
    {-621990000 7200 1 CEST}
    {-605660400 3600 0 CET}
    {-492656400 7200 1 CEST}
    {-481168800 3600 0 CET}
    {-461120400 7200 1 CEST}
    {-449632800 3600 0 CET}
    {-428547600 7200 1 CEST}
    {-418269600 3600 0 CET}
    {-397094400 7200 1 CEST}
    {-386809200 3600 0 CET}
    {323827200 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}

    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}

Changes to library/tzdata/Europe/Copenhagen.

1
2
3
4
5





































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Europe/Copenhagen) $TZData(:Europe/Berlin)






































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Copenhagen) {
    {-9223372036854775808 3020 0 LMT}
    {-2524524620 3020 0 CMT}
    {-2398294220 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680490800 3600 0 CET}
    {-935110800 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-769388400 3600 0 CET}
    {-747010800 7200 1 CEST}
    {-736383600 3600 0 CET}
    {-715215600 7200 1 CEST}
    {-706748400 3600 0 CET}
    {-683161200 7200 1 CEST}
    {-675298800 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Dublin.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Dublin) {
    {-9223372036854775808 -1521 0 LMT}
    {-2821649679 -1521 0 DMT}
    {-1691962479 2079 1 IST}
    {-1680471279 0 0 GMT}
    {-1664143200 3600 1 BST}
    {-1650146400 0 0 GMT}
    {-1633903200 3600 1 BST}
    {-1617487200 0 0 GMT}
    {-1601848800 3600 1 BST}



|
|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Dublin) {
    {-9223372036854775808 -1500 0 LMT}
    {-2821649700 -1521 0 DMT}
    {-1691962479 2079 1 IST}
    {-1680471279 0 0 GMT}
    {-1664143200 3600 1 BST}
    {-1650146400 0 0 GMT}
    {-1633903200 3600 1 BST}
    {-1617487200 0 0 GMT}
    {-1601848800 3600 1 BST}

Changes to library/tzdata/Europe/Istanbul.

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
    {-1522551600 7200 0 EET}
    {-1507514400 10800 1 EEST}
    {-1490583600 7200 0 EET}
    {-1440208800 10800 1 EEST}
    {-1428030000 7200 0 EET}
    {-1409709600 10800 1 EEST}
    {-1396494000 7200 0 EET}
    {-931053600 10800 1 EEST}
    {-922676400 7200 0 EET}
    {-917834400 10800 1 EEST}
    {-892436400 7200 0 EET}
    {-875844000 10800 1 EEST}


    {-764737200 7200 0 EET}
    {-744343200 10800 1 EEST}
    {-733806000 7200 0 EET}
    {-716436000 10800 1 EEST}
    {-701924400 7200 0 EET}
    {-684986400 10800 1 EEST}
    {-670474800 7200 0 EET}
    {-654141600 10800 1 EEST}
    {-639025200 7200 0 EET}
    {-622087200 10800 1 EEST}
    {-606970800 7200 0 EET}
    {-590032800 10800 1 EEST}
    {-575521200 7200 0 EET}
    {-235620000 10800 1 EEST}
    {-194842800 7200 0 EET}
    {-177732000 10800 1 EEST}
    {-165726000 7200 0 EET}






    {107910000 10800 1 EEST}
    {121215600 7200 0 EET}
    {133920000 10800 1 EEST}
    {152665200 7200 0 EET}
    {164678400 10800 1 EEST}
    {184114800 7200 0 EET}
    {196214400 10800 1 EEST}
    {215564400 7200 0 EET}
    {228873600 10800 1 EEST}
    {245804400 7200 0 EET}
    {260323200 10800 1 EEST}


    {267919200 10800 0 +03}



    {277254000 10800 0 +03}
    {428454000 14400 1 +04}


    {433893600 10800 0 +03}
    {468111600 7200 0 EET}
    {482799600 10800 1 EEST}
    {496710000 7200 0 EET}
    {512521200 10800 1 EEST}
    {528246000 7200 0 EET}
    {543970800 10800 1 EEST}
    {559695600 7200 0 EET}
    {575420400 10800 1 EEST}
    {591145200 7200 0 EET}
    {606870000 10800 1 EEST}







|
|



>
>









|


|

|


>
>
>
>
>
>

|

|
|
|
|
|
|
|
|
>
>
|
>
>
>
|
|
>
>
|
|
|
|







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
    {-1522551600 7200 0 EET}
    {-1507514400 10800 1 EEST}
    {-1490583600 7200 0 EET}
    {-1440208800 10800 1 EEST}
    {-1428030000 7200 0 EET}
    {-1409709600 10800 1 EEST}
    {-1396494000 7200 0 EET}
    {-931140000 10800 1 EEST}
    {-922762800 7200 0 EET}
    {-917834400 10800 1 EEST}
    {-892436400 7200 0 EET}
    {-875844000 10800 1 EEST}
    {-857358000 7200 0 EET}
    {-781063200 10800 1 EEST}
    {-764737200 7200 0 EET}
    {-744343200 10800 1 EEST}
    {-733806000 7200 0 EET}
    {-716436000 10800 1 EEST}
    {-701924400 7200 0 EET}
    {-684986400 10800 1 EEST}
    {-670474800 7200 0 EET}
    {-654141600 10800 1 EEST}
    {-639025200 7200 0 EET}
    {-621828000 10800 1 EEST}
    {-606970800 7200 0 EET}
    {-590032800 10800 1 EEST}
    {-575434800 7200 0 EET}
    {-235620000 10800 1 EEST}
    {-228279600 7200 0 EET}
    {-177732000 10800 1 EEST}
    {-165726000 7200 0 EET}
    {10533600 10800 1 EEST}
    {23835600 7200 0 EET}
    {41983200 10800 1 EEST}
    {55285200 7200 0 EET}
    {74037600 10800 1 EEST}
    {87339600 7200 0 EET}
    {107910000 10800 1 EEST}
    {121219200 7200 0 EET}
    {133920000 10800 1 EEST}
    {152676000 7200 0 EET}
    {165362400 10800 1 EEST}
    {183502800 7200 0 EET}
    {202428000 10800 1 EEST}
    {215557200 7200 0 EET}
    {228866400 10800 1 EEST}
    {245797200 7200 0 EET}
    {260316000 10800 1 EEST}
    {277246800 14400 0 +04}
    {291769200 14400 1 +04}
    {308779200 10800 0 +03}
    {323827200 14400 1 +04}
    {340228800 10800 0 +03}
    {354672000 14400 1 +04}
    {371678400 10800 0 +03}
    {386121600 14400 1 +04}
    {403128000 10800 0 +03}
    {428446800 14400 1 +04}
    {433886400 10800 0 +03}
    {482792400 7200 0 EET}
    {482796000 10800 1 EEST}
    {496702800 7200 0 EET}
    {512521200 10800 1 EEST}
    {528246000 7200 0 EET}
    {543970800 10800 1 EEST}
    {559695600 7200 0 EET}
    {575420400 10800 1 EEST}
    {591145200 7200 0 EET}
    {606870000 10800 1 EEST}

Changes to library/tzdata/Europe/Kaliningrad.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    {-1618700400 3600 0 CET}
    {-938905200 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-780368400 7200 0 EET}
    {-778730400 10800 1 EEST}
    {-762663600 7200 0 EET}
    {-749095200 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}







<
|
|
|
|







11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
    {-1618700400 3600 0 CET}
    {-938905200 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}

    {-788922000 7200 0 CET}
    {-778730400 10800 1 CEST}
    {-762663600 7200 0 CET}
    {-757389600 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}

Changes to library/tzdata/Europe/Kiev.

1
2
3
4
5
























































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv
}
set TZData(:Europe/Kiev) $TZData(:Europe/Kyiv)

























































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Kiev) {
    {-9223372036854775808 7324 0 LMT}
    {-2840148124 7324 0 KMT}
    {-1441159324 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-892522800 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-825382800 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {646786800 10800 1 EEST}
    {686102400 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Deleted library/tzdata/Europe/Kyiv.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Kyiv) {
    {-9223372036854775808 7324 0 LMT}
    {-2840148124 7324 0 KMT}
    {-1441159324 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-892522800 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-825382800 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {646786800 10800 1 EEST}
    {686102400 7200 0 EET}
    {701827200 10800 1 EEST}
    {717552000 7200 0 EET}
    {733276800 10800 1 EEST}
    {749001600 7200 0 EET}
    {764726400 10800 1 EEST}
    {780451200 7200 0 EET}
    {796176000 10800 1 EEST}
    {811900800 7200 0 EET}
    {828230400 10800 1 EEST}
    {831938400 10800 0 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































































































































Changes to library/tzdata/Europe/Lisbon.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    {-733366800 0 0 WET}
    {-717631200 3600 1 WEST}
    {-701906400 0 0 WET}
    {-686181600 3600 1 WEST}
    {-670456800 0 0 WET}
    {-654732000 3600 1 WEST}
    {-639007200 0 0 WET}
    {-623282400 3600 1 WEST}
    {-607557600 0 0 WET}
    {-591832800 3600 1 WEST}
    {-575503200 0 0 WET}
    {-559778400 3600 1 WEST}
    {-544053600 0 0 WET}
    {-528328800 3600 1 WEST}
    {-512604000 0 0 WET}
    {-496879200 3600 1 WEST}







<
<







66
67
68
69
70
71
72


73
74
75
76
77
78
79
    {-733366800 0 0 WET}
    {-717631200 3600 1 WEST}
    {-701906400 0 0 WET}
    {-686181600 3600 1 WEST}
    {-670456800 0 0 WET}
    {-654732000 3600 1 WEST}
    {-639007200 0 0 WET}


    {-591832800 3600 1 WEST}
    {-575503200 0 0 WET}
    {-559778400 3600 1 WEST}
    {-544053600 0 0 WET}
    {-528328800 3600 1 WEST}
    {-512604000 0 0 WET}
    {-496879200 3600 1 WEST}

Changes to library/tzdata/Europe/Luxembourg.

1
2
3





















































































































































































































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {
    LoadTimeZoneFile Europe/Brussels





















































































































































































































































































































}
set TZData(:Europe/Luxembourg) $TZData(:Europe/Brussels)

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Luxembourg) {
    {-9223372036854775808 1476 0 LMT}
    {-2069713476 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {-1662343200 7200 1 CEST}
    {-1650157200 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}
    {-1612659600 0 0 WET}
    {-1604278800 3600 1 WEST}
    {-1585519200 0 0 WET}
    {-1574038800 3600 1 WEST}
    {-1552258800 0 0 WET}
    {-1539997200 3600 1 WEST}
    {-1520550000 0 0 WET}
    {-1507510800 3600 1 WEST}
    {-1490572800 0 0 WET}
    {-1473642000 3600 1 WEST}
    {-1459119600 0 0 WET}
    {-1444006800 3600 1 WEST}
    {-1427673600 0 0 WET}
    {-1411866000 3600 1 WEST}
    {-1396224000 0 0 WET}
    {-1379293200 3600 1 WEST}
    {-1364774400 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333324800 0 0 WET}
    {-1316394000 3600 1 WEST}
    {-1301270400 0 0 WET}
    {-1284339600 3600 1 WEST}
    {-1269813600 0 0 WET}
    {-1253484000 3600 1 WEST}
    {-1238364000 0 0 WET}
    {-1221429600 3600 1 WEST}
    {-1206914400 0 0 WET}
    {-1191189600 3600 1 WEST}
    {-1175464800 0 0 WET}
    {-1160344800 3600 1 WEST}
    {-1143410400 0 0 WET}
    {-1127685600 3600 1 WEST}
    {-1111960800 0 0 WET}
    {-1096840800 3600 1 WEST}
    {-1080511200 0 0 WET}
    {-1063576800 3600 1 WEST}
    {-1049061600 0 0 WET}
    {-1033336800 3600 1 WEST}
    {-1017612000 0 0 WET}
    {-1002492000 3600 1 WEST}
    {-986162400 0 0 WET}
    {-969228000 3600 1 WEST}
    {-950479200 0 0 WET}
    {-942012000 3600 1 WEST}
    {-935186400 7200 0 WEST}
    {-857257200 3600 0 WET}
    {-844556400 7200 1 WEST}
    {-828226800 3600 0 WET}
    {-812502000 7200 1 WEST}
    {-797983200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-766623600 3600 0 CET}
    {-745455600 7200 1 CEST}
    {-733273200 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Monaco.

1
2
3























































































































































































































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Paris)]} {
    LoadTimeZoneFile Europe/Paris























































































































































































































































































































}
set TZData(:Europe/Monaco) $TZData(:Europe/Paris)

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Monaco) {
    {-9223372036854775808 1772 0 LMT}
    {-2486680172 561 0 PMT}
    {-1855958961 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}
    {-1604278800 3600 1 WEST}
    {-1585443600 0 0 WET}
    {-1574038800 3600 1 WEST}
    {-1552266000 0 0 WET}
    {-1539997200 3600 1 WEST}
    {-1520557200 0 0 WET}
    {-1507510800 3600 1 WEST}
    {-1490576400 0 0 WET}
    {-1470618000 3600 1 WEST}
    {-1459126800 0 0 WET}
    {-1444006800 3600 1 WEST}
    {-1427677200 0 0 WET}
    {-1411952400 3600 1 WEST}
    {-1396227600 0 0 WET}
    {-1379293200 3600 1 WEST}
    {-1364778000 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333328400 0 0 WET}
    {-1316394000 3600 1 WEST}
    {-1301274000 0 0 WET}
    {-1284339600 3600 1 WEST}
    {-1269824400 0 0 WET}
    {-1253494800 3600 1 WEST}
    {-1238374800 0 0 WET}
    {-1221440400 3600 1 WEST}
    {-1206925200 0 0 WET}
    {-1191200400 3600 1 WEST}
    {-1175475600 0 0 WET}
    {-1160355600 3600 1 WEST}
    {-1143421200 0 0 WET}
    {-1127696400 3600 1 WEST}
    {-1111971600 0 0 WET}
    {-1096851600 3600 1 WEST}
    {-1080522000 0 0 WET}
    {-1063587600 3600 1 WEST}
    {-1049072400 0 0 WET}
    {-1033347600 3600 1 WEST}
    {-1017622800 0 0 WET}
    {-1002502800 3600 1 WEST}
    {-986173200 0 0 WET}
    {-969238800 3600 1 WEST}
    {-950490000 0 0 WET}
    {-942012000 3600 1 WEST}
    {-904438800 7200 1 WEMT}
    {-891136800 3600 1 WEST}
    {-877827600 7200 1 WEMT}
    {-857257200 3600 1 WEST}
    {-844556400 7200 1 WEMT}
    {-828226800 3600 1 WEST}
    {-812502000 7200 1 WEMT}
    {-796266000 3600 1 WEST}
    {-781052400 7200 1 WEMT}
    {-766616400 3600 0 CET}
    {196819200 7200 1 CEST}
    {212540400 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Oslo.

1
2
3
4
5












































































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Europe/Oslo) $TZData(:Europe/Berlin)













































































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Oslo) {
    {-9223372036854775808 2580 0 LMT}
    {-2366757780 3600 0 CET}
    {-1691884800 7200 1 CEST}
    {-1680573600 3600 0 CET}
    {-927511200 7200 0 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-765327600 3600 0 CET}
    {-340844400 7200 1 CEST}
    {-324514800 3600 0 CET}
    {-308790000 7200 1 CEST}
    {-293065200 3600 0 CET}
    {-277340400 7200 1 CEST}
    {-261615600 3600 0 CET}
    {-245890800 7200 1 CEST}
    {-230166000 3600 0 CET}
    {-214441200 7200 1 CEST}
    {-198716400 3600 0 CET}
    {-182991600 7200 1 CEST}
    {-166662000 3600 0 CET}
    {-147913200 7200 1 CEST}
    {-135212400 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Paris.

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Paris) {
    {-9223372036854775808 561 0 LMT}
    {-2486592561 561 0 PMT}
    {-1855958961 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}
    {-1604278800 3600 1 WEST}




|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Paris) {
    {-9223372036854775808 561 0 LMT}
    {-2486678901 561 0 PMT}
    {-1855958901 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}
    {-1604278800 3600 1 WEST}

Changes to library/tzdata/Europe/Rome.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Rome) {
    {-9223372036854775808 2996 0 LMT}
    {-3252098996 2996 0 RMT}
    {-2403565200 3600 0 CET}
    {-1690765200 7200 1 CEST}
    {-1680487200 3600 0 CET}
    {-1664758800 7200 1 CEST}
    {-1648951200 3600 0 CET}
    {-1635123600 7200 1 CEST}
    {-1616896800 3600 0 CET}




|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Rome) {
    {-9223372036854775808 2996 0 LMT}
    {-3259097396 2996 0 RMT}
    {-2403565200 3600 0 CET}
    {-1690765200 7200 1 CEST}
    {-1680487200 3600 0 CET}
    {-1664758800 7200 1 CEST}
    {-1648951200 3600 0 CET}
    {-1635123600 7200 1 CEST}
    {-1616896800 3600 0 CET}

Changes to library/tzdata/Europe/Simferopol.

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
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {631141200 10800 0 MSK}
    {646786800 7200 0 EET}
    {701042400 7200 0 EET}
    {701827200 10800 1 EEST}
    {717552000 7200 0 EET}
    {733276800 10800 1 EEST}
    {749001600 7200 0 EET}
    {764726400 10800 1 EEST}
    {767743200 14400 0 MSD}
    {780447600 10800 0 MSK}
    {796172400 14400 1 MSD}
    {811897200 10800 0 MSK}
    {828219600 14400 1 MSD}
    {846374400 10800 0 MSK}
    {859683600 10800 0 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}







|
|
|
|
|
|

|
|
|

|







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
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {631141200 10800 0 MSK}
    {646786800 7200 0 EET}
    {694216800 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {767743200 14400 0 MSD}
    {780436800 10800 0 MSK}
    {796165200 14400 1 MSD}
    {811886400 10800 0 MSK}
    {828219600 14400 1 MSD}
    {852066000 10800 0 MSK}
    {859683600 10800 0 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}

Changes to library/tzdata/Europe/Stockholm.

1
2
3
4
5























































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Europe/Stockholm) $TZData(:Europe/Berlin)
























































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Stockholm) {
    {-9223372036854775808 4332 0 LMT}
    {-2871681132 3614 0 SET}
    {-2208992414 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Uzhgorod.

1
2
3
4
5



























































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv
}
set TZData(:Europe/Uzhgorod) $TZData(:Europe/Kyiv)




























































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Uzhgorod) {
    {-9223372036854775808 5352 0 LMT}
    {-2500939752 3600 0 CET}
    {-946774800 3600 0 CET}
    {-938905200 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796870800 7200 1 CEST}
    {-794714400 3600 0 CET}
    {-773456400 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {631141200 10800 0 MSK}
    {646786800 3600 0 CET}
    {670384800 7200 0 EET}
    {694216800 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/Europe/Vienna.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-780188400 3600 0 CET}
    {-757386000 3600 0 CET}
    {-748479600 7200 1 CEST}
    {-733273200 3600 0 CET}
    {-717634800 7200 1 CEST}
    {-701910000 3600 0 CET}
    {-684975600 7200 1 CEST}
    {-670460400 3600 0 CET}
    {323823600 7200 1 CEST}
    {338940000 3600 0 CET}
    {347151600 3600 0 CET}







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-780188400 3600 0 CET}
    {-757386000 3600 0 CET}
    {-748479600 7200 1 CEST}
    {-733359600 3600 0 CET}
    {-717634800 7200 1 CEST}
    {-701910000 3600 0 CET}
    {-684975600 7200 1 CEST}
    {-670460400 3600 0 CET}
    {323823600 7200 1 CEST}
    {338940000 3600 0 CET}
    {347151600 3600 0 CET}

Changes to library/tzdata/Europe/Volgograd.

64
65
66
67
68
69
70
71
72
73
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {1540681200 14400 0 +04}
    {1609020000 10800 0 +03}
}







<
<

64
65
66
67
68
69
70


71
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}


}

Changes to library/tzdata/Europe/Zaporozhye.

1
2
3
4
5

























































































































































































































































# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv
}
set TZData(:Europe/Zaporozhye) $TZData(:Europe/Kyiv)


























































































































































































































































<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Zaporozhye) {
    {-9223372036854775808 8440 0 LMT}
    {-2840149240 8400 0 +0220}
    {-1441160400 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-894769200 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-826419600 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {654649200 10800 0 MSK}
    {670374000 10800 0 EEST}
    {686091600 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/Iceland.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan
}
set TZData(:Iceland) $TZData(:Africa/Abidjan)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Atlantic/Reykjavik)]} {
    LoadTimeZoneFile Atlantic/Reykjavik
}
set TZData(:Iceland) $TZData(:Atlantic/Reykjavik)

Changes to library/tzdata/Indian/Christmas.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Bangkok)]} {
    LoadTimeZoneFile Asia/Bangkok
}
set TZData(:Indian/Christmas) $TZData(:Asia/Bangkok)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Christmas) {
    {-9223372036854775808 25372 0 LMT}
    {-2364102172 25200 0 +07}
}

Changes to library/tzdata/Indian/Cocos.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Yangon)]} {
    LoadTimeZoneFile Asia/Yangon
}
set TZData(:Indian/Cocos) $TZData(:Asia/Yangon)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Cocos) {
    {-9223372036854775808 23260 0 LMT}
    {-2209012060 23400 0 +0630}
}

Changes to library/tzdata/Indian/Kerguelen.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Indian/Maldives)]} {
    LoadTimeZoneFile Indian/Maldives
}
set TZData(:Indian/Kerguelen) $TZData(:Indian/Maldives)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Kerguelen) {
    {-9223372036854775808 0 0 -00}
    {-631152000 18000 0 +05}
}

Changes to library/tzdata/Indian/Mahe.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Dubai)]} {
    LoadTimeZoneFile Asia/Dubai
}
set TZData(:Indian/Mahe) $TZData(:Asia/Dubai)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Mahe) {
    {-9223372036854775808 13308 0 LMT}
    {-2006653308 14400 0 +04}
}

Changes to library/tzdata/Indian/Reunion.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Dubai)]} {
    LoadTimeZoneFile Asia/Dubai
}
set TZData(:Indian/Reunion) $TZData(:Asia/Dubai)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Reunion) {
    {-9223372036854775808 13312 0 LMT}
    {-1848886912 14400 0 +04}
}

Changes to library/tzdata/Pacific/Apia.

24
25
26
27
28
29
30





























































































































































31
    {1522504800 46800 0 +13}
    {1538229600 50400 1 +13}
    {1554559200 46800 0 +13}
    {1569679200 50400 1 +13}
    {1586008800 46800 0 +13}
    {1601128800 50400 1 +13}
    {1617458400 46800 0 +13}





























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    {1522504800 46800 0 +13}
    {1538229600 50400 1 +13}
    {1554559200 46800 0 +13}
    {1569679200 50400 1 +13}
    {1586008800 46800 0 +13}
    {1601128800 50400 1 +13}
    {1617458400 46800 0 +13}
    {1632578400 50400 1 +13}
    {1648908000 46800 0 +13}
    {1664028000 50400 1 +13}
    {1680357600 46800 0 +13}
    {1695477600 50400 1 +13}
    {1712412000 46800 0 +13}
    {1727532000 50400 1 +13}
    {1743861600 46800 0 +13}
    {1758981600 50400 1 +13}
    {1775311200 46800 0 +13}
    {1790431200 50400 1 +13}
    {1806760800 46800 0 +13}
    {1821880800 50400 1 +13}
    {1838210400 46800 0 +13}
    {1853330400 50400 1 +13}
    {1869660000 46800 0 +13}
    {1885384800 50400 1 +13}
    {1901714400 46800 0 +13}
    {1916834400 50400 1 +13}
    {1933164000 46800 0 +13}
    {1948284000 50400 1 +13}
    {1964613600 46800 0 +13}
    {1979733600 50400 1 +13}
    {1996063200 46800 0 +13}
    {2011183200 50400 1 +13}
    {2027512800 46800 0 +13}
    {2042632800 50400 1 +13}
    {2058962400 46800 0 +13}
    {2074687200 50400 1 +13}
    {2091016800 46800 0 +13}
    {2106136800 50400 1 +13}
    {2122466400 46800 0 +13}
    {2137586400 50400 1 +13}
    {2153916000 46800 0 +13}
    {2169036000 50400 1 +13}
    {2185365600 46800 0 +13}
    {2200485600 50400 1 +13}
    {2216815200 46800 0 +13}
    {2232540000 50400 1 +13}
    {2248869600 46800 0 +13}
    {2263989600 50400 1 +13}
    {2280319200 46800 0 +13}
    {2295439200 50400 1 +13}
    {2311768800 46800 0 +13}
    {2326888800 50400 1 +13}
    {2343218400 46800 0 +13}
    {2358338400 50400 1 +13}
    {2374668000 46800 0 +13}
    {2389788000 50400 1 +13}
    {2406117600 46800 0 +13}
    {2421842400 50400 1 +13}
    {2438172000 46800 0 +13}
    {2453292000 50400 1 +13}
    {2469621600 46800 0 +13}
    {2484741600 50400 1 +13}
    {2501071200 46800 0 +13}
    {2516191200 50400 1 +13}
    {2532520800 46800 0 +13}
    {2547640800 50400 1 +13}
    {2563970400 46800 0 +13}
    {2579090400 50400 1 +13}
    {2596024800 46800 0 +13}
    {2611144800 50400 1 +13}
    {2627474400 46800 0 +13}
    {2642594400 50400 1 +13}
    {2658924000 46800 0 +13}
    {2674044000 50400 1 +13}
    {2690373600 46800 0 +13}
    {2705493600 50400 1 +13}
    {2721823200 46800 0 +13}
    {2736943200 50400 1 +13}
    {2753272800 46800 0 +13}
    {2768997600 50400 1 +13}
    {2785327200 46800 0 +13}
    {2800447200 50400 1 +13}
    {2816776800 46800 0 +13}
    {2831896800 50400 1 +13}
    {2848226400 46800 0 +13}
    {2863346400 50400 1 +13}
    {2879676000 46800 0 +13}
    {2894796000 50400 1 +13}
    {2911125600 46800 0 +13}
    {2926245600 50400 1 +13}
    {2942575200 46800 0 +13}
    {2958300000 50400 1 +13}
    {2974629600 46800 0 +13}
    {2989749600 50400 1 +13}
    {3006079200 46800 0 +13}
    {3021199200 50400 1 +13}
    {3037528800 46800 0 +13}
    {3052648800 50400 1 +13}
    {3068978400 46800 0 +13}
    {3084098400 50400 1 +13}
    {3100428000 46800 0 +13}
    {3116152800 50400 1 +13}
    {3132482400 46800 0 +13}
    {3147602400 50400 1 +13}
    {3163932000 46800 0 +13}
    {3179052000 50400 1 +13}
    {3195381600 46800 0 +13}
    {3210501600 50400 1 +13}
    {3226831200 46800 0 +13}
    {3241951200 50400 1 +13}
    {3258280800 46800 0 +13}
    {3273400800 50400 1 +13}
    {3289730400 46800 0 +13}
    {3305455200 50400 1 +13}
    {3321784800 46800 0 +13}
    {3336904800 50400 1 +13}
    {3353234400 46800 0 +13}
    {3368354400 50400 1 +13}
    {3384684000 46800 0 +13}
    {3399804000 50400 1 +13}
    {3416133600 46800 0 +13}
    {3431253600 50400 1 +13}
    {3447583200 46800 0 +13}
    {3462703200 50400 1 +13}
    {3479637600 46800 0 +13}
    {3494757600 50400 1 +13}
    {3511087200 46800 0 +13}
    {3526207200 50400 1 +13}
    {3542536800 46800 0 +13}
    {3557656800 50400 1 +13}
    {3573986400 46800 0 +13}
    {3589106400 50400 1 +13}
    {3605436000 46800 0 +13}
    {3620556000 50400 1 +13}
    {3636885600 46800 0 +13}
    {3652610400 50400 1 +13}
    {3668940000 46800 0 +13}
    {3684060000 50400 1 +13}
    {3700389600 46800 0 +13}
    {3715509600 50400 1 +13}
    {3731839200 46800 0 +13}
    {3746959200 50400 1 +13}
    {3763288800 46800 0 +13}
    {3778408800 50400 1 +13}
    {3794738400 46800 0 +13}
    {3809858400 50400 1 +13}
    {3826188000 46800 0 +13}
    {3841912800 50400 1 +13}
    {3858242400 46800 0 +13}
    {3873362400 50400 1 +13}
    {3889692000 46800 0 +13}
    {3904812000 50400 1 +13}
    {3921141600 46800 0 +13}
    {3936261600 50400 1 +13}
    {3952591200 46800 0 +13}
    {3967711200 50400 1 +13}
    {3984040800 46800 0 +13}
    {3999765600 50400 1 +13}
    {4016095200 46800 0 +13}
    {4031215200 50400 1 +13}
    {4047544800 46800 0 +13}
    {4062664800 50400 1 +13}
    {4078994400 46800 0 +13}
    {4094114400 50400 1 +13}
}

Changes to library/tzdata/Pacific/Chuuk.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Pacific/Chuuk) $TZData(:Pacific/Port_Moresby)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Chuuk) {
    {-9223372036854775808 36428 0 LMT}
    {-2177489228 36000 0 +10}
}

Changes to library/tzdata/Pacific/Easter.

99
100
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
136
137
138
139
140
141
142


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    {1410062400 -18000 1 -06}
    {1463281200 -21600 0 -06}
    {1471147200 -18000 1 -06}
    {1494730800 -21600 0 -06}
    {1502596800 -18000 1 -06}
    {1526180400 -21600 0 -06}
    {1534046400 -18000 1 -06}
    {1554606000 -21600 0 -06}
    {1567915200 -18000 1 -06}
    {1586055600 -21600 0 -06}
    {1599364800 -18000 1 -06}
    {1617505200 -21600 0 -06}
    {1630814400 -18000 1 -06}
    {1648954800 -21600 0 -06}
    {1662868800 -18000 1 -06}
    {1680404400 -21600 0 -06}
    {1693713600 -18000 1 -06}
    {1712458800 -21600 0 -06}
    {1725768000 -18000 1 -06}
    {1743908400 -21600 0 -06}
    {1757217600 -18000 1 -06}
    {1775358000 -21600 0 -06}
    {1788667200 -18000 1 -06}
    {1806807600 -21600 0 -06}
    {1820116800 -18000 1 -06}
    {1838257200 -21600 0 -06}
    {1851566400 -18000 1 -06}
    {1870311600 -21600 0 -06}
    {1883016000 -18000 1 -06}
    {1901761200 -21600 0 -06}
    {1915070400 -18000 1 -06}
    {1933210800 -21600 0 -06}
    {1946520000 -18000 1 -06}
    {1964660400 -21600 0 -06}
    {1977969600 -18000 1 -06}
    {1996110000 -21600 0 -06}
    {2009419200 -18000 1 -06}
    {2027559600 -21600 0 -06}
    {2040868800 -18000 1 -06}
    {2059614000 -21600 0 -06}
    {2072318400 -18000 1 -06}
    {2091063600 -21600 0 -06}
    {2104372800 -18000 1 -06}
    {2122513200 -21600 0 -06}


    {2135822400 -18000 1 -06}
    {2153962800 -21600 0 -06}
    {2167272000 -18000 1 -06}
    {2185412400 -21600 0 -06}
    {2198721600 -18000 1 -06}
    {2217466800 -21600 0 -06}
    {2230171200 -18000 1 -06}
    {2248916400 -21600 0 -06}
    {2262225600 -18000 1 -06}
    {2280366000 -21600 0 -06}
    {2293675200 -18000 1 -06}
    {2311815600 -21600 0 -06}
    {2325124800 -18000 1 -06}
    {2343265200 -21600 0 -06}
    {2356574400 -18000 1 -06}
    {2374714800 -21600 0 -06}
    {2388024000 -18000 1 -06}
    {2406769200 -21600 0 -06}
    {2419473600 -18000 1 -06}
    {2438218800 -21600 0 -06}
    {2451528000 -18000 1 -06}
    {2469668400 -21600 0 -06}
    {2482977600 -18000 1 -06}
    {2501118000 -21600 0 -06}
    {2514427200 -18000 1 -06}
    {2532567600 -21600 0 -06}
    {2545876800 -18000 1 -06}
    {2564017200 -21600 0 -06}
    {2577326400 -18000 1 -06}
    {2596071600 -21600 0 -06}
    {2609380800 -18000 1 -06}
    {2627521200 -21600 0 -06}
    {2640830400 -18000 1 -06}
    {2658970800 -21600 0 -06}
    {2672280000 -18000 1 -06}
    {2690420400 -21600 0 -06}
    {2703729600 -18000 1 -06}
    {2721870000 -21600 0 -06}
    {2735179200 -18000 1 -06}
    {2753924400 -21600 0 -06}
    {2766628800 -18000 1 -06}
    {2785374000 -21600 0 -06}
    {2798683200 -18000 1 -06}
    {2816823600 -21600 0 -06}
    {2830132800 -18000 1 -06}
    {2848273200 -21600 0 -06}
    {2861582400 -18000 1 -06}
    {2879722800 -21600 0 -06}
    {2893032000 -18000 1 -06}
    {2911172400 -21600 0 -06}
    {2924481600 -18000 1 -06}
    {2943226800 -21600 0 -06}
    {2955931200 -18000 1 -06}
    {2974676400 -21600 0 -06}
    {2987985600 -18000 1 -06}
    {3006126000 -21600 0 -06}
    {3019435200 -18000 1 -06}
    {3037575600 -21600 0 -06}
    {3050884800 -18000 1 -06}
    {3069025200 -21600 0 -06}
    {3082334400 -18000 1 -06}
    {3101079600 -21600 0 -06}
    {3113784000 -18000 1 -06}
    {3132529200 -21600 0 -06}
    {3145838400 -18000 1 -06}
    {3163978800 -21600 0 -06}
    {3177288000 -18000 1 -06}
    {3195428400 -21600 0 -06}
    {3208737600 -18000 1 -06}
    {3226878000 -21600 0 -06}
    {3240187200 -18000 1 -06}
    {3258327600 -21600 0 -06}
    {3271636800 -18000 1 -06}
    {3290382000 -21600 0 -06}
    {3303086400 -18000 1 -06}
    {3321831600 -21600 0 -06}
    {3335140800 -18000 1 -06}
    {3353281200 -21600 0 -06}
    {3366590400 -18000 1 -06}
    {3384730800 -21600 0 -06}
    {3398040000 -18000 1 -06}
    {3416180400 -21600 0 -06}
    {3429489600 -18000 1 -06}
    {3447630000 -21600 0 -06}
    {3460939200 -18000 1 -06}
    {3479684400 -21600 0 -06}
    {3492993600 -18000 1 -06}
    {3511134000 -21600 0 -06}
    {3524443200 -18000 1 -06}
    {3542583600 -21600 0 -06}
    {3555892800 -18000 1 -06}
    {3574033200 -21600 0 -06}
    {3587342400 -18000 1 -06}
    {3605482800 -21600 0 -06}
    {3618792000 -18000 1 -06}
    {3637537200 -21600 0 -06}
    {3650241600 -18000 1 -06}
    {3668986800 -21600 0 -06}
    {3682296000 -18000 1 -06}
    {3700436400 -21600 0 -06}
    {3713745600 -18000 1 -06}
    {3731886000 -21600 0 -06}
    {3745195200 -18000 1 -06}
    {3763335600 -21600 0 -06}
    {3776644800 -18000 1 -06}
    {3794785200 -21600 0 -06}
    {3808094400 -18000 1 -06}
    {3826839600 -21600 0 -06}
    {3839544000 -18000 1 -06}
    {3858289200 -21600 0 -06}
    {3871598400 -18000 1 -06}
    {3889738800 -21600 0 -06}
    {3903048000 -18000 1 -06}
    {3921188400 -21600 0 -06}
    {3934497600 -18000 1 -06}
    {3952638000 -21600 0 -06}
    {3965947200 -18000 1 -06}
    {3984692400 -21600 0 -06}
    {3997396800 -18000 1 -06}
    {4016142000 -21600 0 -06}
    {4029451200 -18000 1 -06}
    {4047591600 -21600 0 -06}
    {4060900800 -18000 1 -06}
    {4079041200 -21600 0 -06}
    {4092350400 -18000 1 -06}
}







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

99
100
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    {1410062400 -18000 1 -06}
    {1463281200 -21600 0 -06}
    {1471147200 -18000 1 -06}
    {1494730800 -21600 0 -06}
    {1502596800 -18000 1 -06}
    {1526180400 -21600 0 -06}
    {1534046400 -18000 1 -06}
    {1557630000 -21600 0 -06}
    {1565496000 -18000 1 -06}
    {1589079600 -21600 0 -06}
    {1596945600 -18000 1 -06}
    {1620529200 -21600 0 -06}
    {1629000000 -18000 1 -06}
    {1652583600 -21600 0 -06}
    {1660449600 -18000 1 -06}
    {1684033200 -21600 0 -06}
    {1691899200 -18000 1 -06}
    {1715482800 -21600 0 -06}
    {1723348800 -18000 1 -06}
    {1746932400 -21600 0 -06}
    {1754798400 -18000 1 -06}
    {1778382000 -21600 0 -06}
    {1786248000 -18000 1 -06}
    {1809831600 -21600 0 -06}
    {1818302400 -18000 1 -06}
    {1841886000 -21600 0 -06}
    {1849752000 -18000 1 -06}
    {1873335600 -21600 0 -06}
    {1881201600 -18000 1 -06}
    {1904785200 -21600 0 -06}
    {1912651200 -18000 1 -06}
    {1936234800 -21600 0 -06}
    {1944100800 -18000 1 -06}
    {1967684400 -21600 0 -06}
    {1976155200 -18000 1 -06}
    {1999738800 -21600 0 -06}
    {2007604800 -18000 1 -06}
    {2031188400 -21600 0 -06}
    {2039054400 -18000 1 -06}
    {2062638000 -21600 0 -06}
    {2070504000 -18000 1 -06}
    {2094087600 -21600 0 -06}
    {2101953600 -18000 1 -06}
    {2125537200 -21600 0 -06}
    {2133403200 -18000 1 -06}
    {2156986800 -21600 0 -06}
    {2165457600 -18000 1 -06}
    {2189041200 -21600 0 -06}
    {2196907200 -18000 1 -06}
    {2220490800 -21600 0 -06}
    {2228356800 -18000 1 -06}
    {2251940400 -21600 0 -06}
    {2259806400 -18000 1 -06}
    {2283390000 -21600 0 -06}
    {2291256000 -18000 1 -06}
    {2314839600 -21600 0 -06}
    {2322705600 -18000 1 -06}
    {2346894000 -21600 0 -06}
    {2354760000 -18000 1 -06}
    {2378343600 -21600 0 -06}
    {2386209600 -18000 1 -06}
    {2409793200 -21600 0 -06}
    {2417659200 -18000 1 -06}
    {2441242800 -21600 0 -06}
    {2449108800 -18000 1 -06}
    {2472692400 -21600 0 -06}
    {2480558400 -18000 1 -06}
    {2504142000 -21600 0 -06}
    {2512612800 -18000 1 -06}
    {2536196400 -21600 0 -06}
    {2544062400 -18000 1 -06}
    {2567646000 -21600 0 -06}
    {2575512000 -18000 1 -06}
    {2599095600 -21600 0 -06}
    {2606961600 -18000 1 -06}
    {2630545200 -21600 0 -06}
    {2638411200 -18000 1 -06}
    {2661994800 -21600 0 -06}
    {2669860800 -18000 1 -06}
    {2693444400 -21600 0 -06}
    {2701915200 -18000 1 -06}
    {2725498800 -21600 0 -06}
    {2733364800 -18000 1 -06}
    {2756948400 -21600 0 -06}
    {2764814400 -18000 1 -06}
    {2788398000 -21600 0 -06}
    {2796264000 -18000 1 -06}
    {2819847600 -21600 0 -06}
    {2827713600 -18000 1 -06}
    {2851297200 -21600 0 -06}
    {2859768000 -18000 1 -06}
    {2883351600 -21600 0 -06}
    {2891217600 -18000 1 -06}
    {2914801200 -21600 0 -06}
    {2922667200 -18000 1 -06}


    {2946250800 -21600 0 -06}
    {2954116800 -18000 1 -06}
    {2977700400 -21600 0 -06}
    {2985566400 -18000 1 -06}
    {3009150000 -21600 0 -06}
    {3017016000 -18000 1 -06}
    {3040599600 -21600 0 -06}
    {3049070400 -18000 1 -06}
    {3072654000 -21600 0 -06}
    {3080520000 -18000 1 -06}
    {3104103600 -21600 0 -06}
    {3111969600 -18000 1 -06}
    {3135553200 -21600 0 -06}
    {3143419200 -18000 1 -06}
    {3167002800 -21600 0 -06}
    {3174868800 -18000 1 -06}
    {3198452400 -21600 0 -06}
    {3206318400 -18000 1 -06}
    {3230506800 -21600 0 -06}
    {3238372800 -18000 1 -06}
    {3261956400 -21600 0 -06}
    {3269822400 -18000 1 -06}
    {3293406000 -21600 0 -06}
    {3301272000 -18000 1 -06}
    {3324855600 -21600 0 -06}
    {3332721600 -18000 1 -06}
    {3356305200 -21600 0 -06}
    {3364171200 -18000 1 -06}
    {3387754800 -21600 0 -06}
    {3396225600 -18000 1 -06}
    {3419809200 -21600 0 -06}
    {3427675200 -18000 1 -06}
    {3451258800 -21600 0 -06}
    {3459124800 -18000 1 -06}
    {3482708400 -21600 0 -06}
    {3490574400 -18000 1 -06}
    {3514158000 -21600 0 -06}
    {3522024000 -18000 1 -06}
    {3545607600 -21600 0 -06}
    {3553473600 -18000 1 -06}
    {3577057200 -21600 0 -06}
    {3585528000 -18000 1 -06}
    {3609111600 -21600 0 -06}
    {3616977600 -18000 1 -06}
    {3640561200 -21600 0 -06}
    {3648427200 -18000 1 -06}
    {3672010800 -21600 0 -06}
    {3679876800 -18000 1 -06}
    {3703460400 -21600 0 -06}
    {3711326400 -18000 1 -06}
    {3734910000 -21600 0 -06}
    {3743380800 -18000 1 -06}
    {3766964400 -21600 0 -06}
    {3774830400 -18000 1 -06}
    {3798414000 -21600 0 -06}
    {3806280000 -18000 1 -06}
    {3829863600 -21600 0 -06}
    {3837729600 -18000 1 -06}
    {3861313200 -21600 0 -06}
    {3869179200 -18000 1 -06}
    {3892762800 -21600 0 -06}
    {3900628800 -18000 1 -06}
    {3924212400 -21600 0 -06}
    {3932683200 -18000 1 -06}
    {3956266800 -21600 0 -06}
    {3964132800 -18000 1 -06}
    {3987716400 -21600 0 -06}
    {3995582400 -18000 1 -06}
    {4019166000 -21600 0 -06}
    {4027032000 -18000 1 -06}
    {4050615600 -21600 0 -06}
    {4058481600 -18000 1 -06}
    {4082065200 -21600 0 -06}
    {4089931200 -18000 1 -06}
}

Changes to library/tzdata/Pacific/Efate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Efate) {
    {-9223372036854775808 40396 0 LMT}
    {-1829387596 39600 0 +11}
    {125409600 43200 1 +11}
    {133876800 39600 0 +11}
    {433256400 43200 1 +11}
    {448977600 39600 0 +11}
    {464706000 43200 1 +11}
    {480427200 39600 0 +11}
    {496760400 43200 1 +11}
    {511876800 39600 0 +11}
    {528210000 43200 1 +11}
    {543931200 39600 0 +11}
    {559659600 43200 1 +11}
    {575380800 39600 0 +11}





<
<


|







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Efate) {
    {-9223372036854775808 40396 0 LMT}
    {-1829387596 39600 0 +11}


    {433256400 43200 1 +11}
    {448977600 39600 0 +11}
    {467298000 43200 1 +11}
    {480427200 39600 0 +11}
    {496760400 43200 1 +11}
    {511876800 39600 0 +11}
    {528210000 43200 1 +11}
    {543931200 39600 0 +11}
    {559659600 43200 1 +11}
    {575380800 39600 0 +11}

Changes to library/tzdata/Pacific/Enderbury.

1
2
3
4
5





# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Kanton)]} {
    LoadTimeZoneFile Pacific/Kanton
}
set TZData(:Pacific/Enderbury) $TZData(:Pacific/Kanton)






<
<
|
|
>
>
>
>
>
1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Enderbury) {
    {-9223372036854775808 -41060 0 LMT}
    {-2177411740 -43200 0 -12}
    {307627200 -39600 0 -11}
    {788871600 46800 0 +13}
}

Changes to library/tzdata/Pacific/Fiji.

22
23
24
25
26
27
28


















29






30












































31












































































32












33

34
    {1446300000 46800 1 +12}
    {1452952800 43200 0 +12}
    {1478354400 46800 1 +12}
    {1484402400 43200 0 +12}
    {1509804000 46800 1 +12}
    {1515852000 43200 0 +12}
    {1541253600 46800 1 +12}


















    {1547301600 43200 0 +12}






    {1573308000 46800 1 +12}












































    {1578751200 43200 0 +12}












































































    {1608386400 46800 1 +12}












    {1610805600 43200 0 +12}

}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    {1446300000 46800 1 +12}
    {1452952800 43200 0 +12}
    {1478354400 46800 1 +12}
    {1484402400 43200 0 +12}
    {1509804000 46800 1 +12}
    {1515852000 43200 0 +12}
    {1541253600 46800 1 +12}
    {1547906400 43200 0 +12}
    {1572703200 46800 1 +12}
    {1579356000 43200 0 +12}
    {1604152800 46800 1 +12}
    {1610805600 43200 0 +12}
    {1636207200 46800 1 +12}
    {1642255200 43200 0 +12}
    {1667656800 46800 1 +12}
    {1673704800 43200 0 +12}
    {1699106400 46800 1 +12}
    {1705154400 43200 0 +12}
    {1730556000 46800 1 +12}
    {1737208800 43200 0 +12}
    {1762005600 46800 1 +12}
    {1768658400 43200 0 +12}
    {1793455200 46800 1 +12}
    {1800108000 43200 0 +12}
    {1825509600 46800 1 +12}
    {1831557600 43200 0 +12}
    {1856959200 46800 1 +12}
    {1863007200 43200 0 +12}
    {1888408800 46800 1 +12}
    {1895061600 43200 0 +12}
    {1919858400 46800 1 +12}
    {1926511200 43200 0 +12}
    {1951308000 46800 1 +12}
    {1957960800 43200 0 +12}
    {1983362400 46800 1 +12}
    {1989410400 43200 0 +12}
    {2014812000 46800 1 +12}
    {2020860000 43200 0 +12}
    {2046261600 46800 1 +12}
    {2052309600 43200 0 +12}
    {2077711200 46800 1 +12}
    {2084364000 43200 0 +12}
    {2109160800 46800 1 +12}
    {2115813600 43200 0 +12}
    {2140610400 46800 1 +12}
    {2147263200 43200 0 +12}
    {2172664800 46800 1 +12}
    {2178712800 43200 0 +12}
    {2204114400 46800 1 +12}
    {2210162400 43200 0 +12}
    {2235564000 46800 1 +12}
    {2242216800 43200 0 +12}
    {2267013600 46800 1 +12}
    {2273666400 43200 0 +12}
    {2298463200 46800 1 +12}
    {2305116000 43200 0 +12}
    {2329912800 46800 1 +12}
    {2336565600 43200 0 +12}
    {2361967200 46800 1 +12}
    {2368015200 43200 0 +12}
    {2393416800 46800 1 +12}
    {2399464800 43200 0 +12}
    {2424866400 46800 1 +12}
    {2431519200 43200 0 +12}
    {2456316000 46800 1 +12}
    {2462968800 43200 0 +12}
    {2487765600 46800 1 +12}
    {2494418400 43200 0 +12}
    {2519820000 46800 1 +12}
    {2525868000 43200 0 +12}
    {2551269600 46800 1 +12}
    {2557317600 43200 0 +12}
    {2582719200 46800 1 +12}
    {2588767200 43200 0 +12}
    {2614168800 46800 1 +12}
    {2620821600 43200 0 +12}
    {2645618400 46800 1 +12}
    {2652271200 43200 0 +12}
    {2677068000 46800 1 +12}
    {2683720800 43200 0 +12}
    {2709122400 46800 1 +12}
    {2715170400 43200 0 +12}
    {2740572000 46800 1 +12}
    {2746620000 43200 0 +12}
    {2772021600 46800 1 +12}
    {2778674400 43200 0 +12}
    {2803471200 46800 1 +12}
    {2810124000 43200 0 +12}
    {2834920800 46800 1 +12}
    {2841573600 43200 0 +12}
    {2866975200 46800 1 +12}
    {2873023200 43200 0 +12}
    {2898424800 46800 1 +12}
    {2904472800 43200 0 +12}
    {2929874400 46800 1 +12}
    {2935922400 43200 0 +12}
    {2961324000 46800 1 +12}
    {2967976800 43200 0 +12}
    {2992773600 46800 1 +12}
    {2999426400 43200 0 +12}
    {3024223200 46800 1 +12}
    {3030876000 43200 0 +12}
    {3056277600 46800 1 +12}
    {3062325600 43200 0 +12}
    {3087727200 46800 1 +12}
    {3093775200 43200 0 +12}
    {3119176800 46800 1 +12}
    {3125829600 43200 0 +12}
    {3150626400 46800 1 +12}
    {3157279200 43200 0 +12}
    {3182076000 46800 1 +12}
    {3188728800 43200 0 +12}
    {3213525600 46800 1 +12}
    {3220178400 43200 0 +12}
    {3245580000 46800 1 +12}
    {3251628000 43200 0 +12}
    {3277029600 46800 1 +12}
    {3283077600 43200 0 +12}
    {3308479200 46800 1 +12}
    {3315132000 43200 0 +12}
    {3339928800 46800 1 +12}
    {3346581600 43200 0 +12}
    {3371378400 46800 1 +12}
    {3378031200 43200 0 +12}
    {3403432800 46800 1 +12}
    {3409480800 43200 0 +12}
    {3434882400 46800 1 +12}
    {3440930400 43200 0 +12}
    {3466332000 46800 1 +12}
    {3472380000 43200 0 +12}
    {3497781600 46800 1 +12}
    {3504434400 43200 0 +12}
    {3529231200 46800 1 +12}
    {3535884000 43200 0 +12}
    {3560680800 46800 1 +12}
    {3567333600 43200 0 +12}
    {3592735200 46800 1 +12}
    {3598783200 43200 0 +12}
    {3624184800 46800 1 +12}
    {3630232800 43200 0 +12}
    {3655634400 46800 1 +12}
    {3662287200 43200 0 +12}
    {3687084000 46800 1 +12}
    {3693736800 43200 0 +12}
    {3718533600 46800 1 +12}
    {3725186400 43200 0 +12}
    {3750588000 46800 1 +12}
    {3756636000 43200 0 +12}
    {3782037600 46800 1 +12}
    {3788085600 43200 0 +12}
    {3813487200 46800 1 +12}
    {3819535200 43200 0 +12}
    {3844936800 46800 1 +12}
    {3851589600 43200 0 +12}
    {3876386400 46800 1 +12}
    {3883039200 43200 0 +12}
    {3907836000 46800 1 +12}
    {3914488800 43200 0 +12}
    {3939890400 46800 1 +12}
    {3945938400 43200 0 +12}
    {3971340000 46800 1 +12}
    {3977388000 43200 0 +12}
    {4002789600 46800 1 +12}
    {4009442400 43200 0 +12}
    {4034239200 46800 1 +12}
    {4040892000 43200 0 +12}
    {4065688800 46800 1 +12}
    {4072341600 43200 0 +12}
    {4097138400 46800 1 +12}
}

Changes to library/tzdata/Pacific/Funafuti.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa
}
set TZData(:Pacific/Funafuti) $TZData(:Pacific/Tarawa)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Funafuti) {
    {-9223372036854775808 43012 0 LMT}
    {-2177495812 43200 0 +12}
}

Changes to library/tzdata/Pacific/Guam.

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Guam) {
    {-9223372036854775808 -51660 0 LMT}
    {-3944626740 34740 0 LMT}
    {-2177487540 36000 0 GST}
    {-885549600 32400 0 +09}
    {-802256400 36000 0 GST}
    {-331891200 39600 1 GDT}
    {-281610000 36000 0 GST}
    {-73728000 39600 1 GDT}
    {-29415540 36000 0 GST}
    {-16704000 39600 1 GDT}
    {-10659600 36000 0 GST}
    {9907200 39600 1 GDT}
    {21394800 36000 0 GST}
    {41356800 39600 1 GDT}
    {52844400 36000 0 GST}
    {124819200 39600 1 GDT}
    {130863600 36000 0 GST}
    {201888000 39600 1 GDT}
    {209487660 36000 0 GST}
    {230659200 39600 1 GDT}
    {241542000 36000 0 GST}
    {977493600 36000 0 ChST}
}






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


1
2
3
4
5
6


















7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Guam) {
    {-9223372036854775808 -51660 0 LMT}
    {-3944626740 34740 0 LMT}
    {-2177487540 36000 0 GST}


















    {977493600 36000 0 ChST}
}

Changes to library/tzdata/Pacific/Honolulu.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Honolulu) {
    {-9223372036854775808 -37886 0 LMT}
    {-2334101314 -37800 0 HST}
    {-1157283000 -34200 1 HDT}
    {-1155436200 -34200 0 HST}
    {-880201800 -34200 1 HWT}
    {-769395600 -34200 1 HPT}
    {-765376200 -37800 0 HST}
    {-712150200 -36000 0 HST}
}






|
|
<



1
2
3
4
5
6
7
8

9
10
11
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Honolulu) {
    {-9223372036854775808 -37886 0 LMT}
    {-2334101314 -37800 0 HST}
    {-1157283000 -34200 1 HDT}
    {-1155436200 -37800 0 HST}
    {-880198200 -34200 1 HDT}

    {-765376200 -37800 0 HST}
    {-712150200 -36000 0 HST}
}

Deleted library/tzdata/Pacific/Kanton.

1
2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kanton) {
    {-9223372036854775808 0 0 -00}
    {-1020470400 -43200 0 -12}
    {307627200 -39600 0 -11}
    {788871600 46800 0 +13}
}
<
<
<
<
<
<
<
<
















Changes to library/tzdata/Pacific/Kosrae.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kosrae) {
    {-9223372036854775808 -47284 0 LMT}
    {-3944631116 39116 0 LMT}
    {-2177491916 39600 0 +11}
    {-1743678000 32400 0 +09}
    {-1606813200 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-770634000 39600 0 +11}
    {-7988400 43200 0 +12}
    {915105600 39600 0 +11}
}



|
<

<
<
<
<
<



1
2
3
4

5





6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kosrae) {
    {-9223372036854775808 39116 0 LMT}

    {-2177491916 39600 0 +11}





    {-7988400 43200 0 +12}
    {915105600 39600 0 +11}
}

Changes to library/tzdata/Pacific/Kwajalein.

1
2
3
4
5
6
7
8
9
10
11
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kwajalein) {
    {-9223372036854775808 40160 0 LMT}
    {-2177492960 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-817462800 39600 0 +11}
    {-7988400 -43200 0 -12}
    {745934400 43200 0 +12}
}





<
<
<

|

1
2
3
4
5



6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kwajalein) {
    {-9223372036854775808 40160 0 LMT}
    {-2177492960 39600 0 +11}



    {-7988400 -43200 0 -12}
    {745848000 43200 0 +12}
}

Changes to library/tzdata/Pacific/Majuro.

1
2
3
4
5




# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa
}
set TZData(:Pacific/Majuro) $TZData(:Pacific/Tarawa)





<
<
|
|
>
>
>
>
1


2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Majuro) {
    {-9223372036854775808 41088 0 LMT}
    {-2177493888 39600 0 +11}
    {-7988400 43200 0 +12}
}

Changes to library/tzdata/Pacific/Nauru.

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Nauru) {
    {-9223372036854775808 40060 0 LMT}
    {-1545131260 41400 0 +1130}
    {-862918200 32400 0 +09}
    {-767350800 41400 0 +1130}
    {287418600 43200 0 +12}
}





|
|
|

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Nauru) {
    {-9223372036854775808 40060 0 LMT}
    {-1545131260 41400 0 +1130}
    {-877347000 32400 0 +09}
    {-800960400 41400 0 +1130}
    {294323400 43200 0 +12}
}

Changes to library/tzdata/Pacific/Niue.

1
2
3
4
5

6
7
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Niue) {
    {-9223372036854775808 -40780 0 LMT}
    {-543069620 -40800 0 -1120}

    {-173623200 -39600 0 -11}
}




|
>
|

1
2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Niue) {
    {-9223372036854775808 -40780 0 LMT}
    {-2177412020 -40800 0 -1120}
    {-599575200 -41400 0 -1130}
    {276089400 -39600 0 -11}
}

Changes to library/tzdata/Pacific/Norfolk.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Norfolk) {
    {-9223372036854775808 40312 0 LMT}
    {-2177493112 40320 0 +1112}
    {-599656320 41400 0 +1130}
    {152029800 45000 1 +1230}
    {162916200 41400 0 +1130}
    {1443882600 39600 0 +11}
    {1561899600 39600 0 +12}
    {1570287600 43200 1 +12}
    {1586012400 39600 0 +12}
    {1601737200 43200 1 +12}
    {1617462000 39600 0 +12}
    {1633186800 43200 1 +12}
    {1648911600 39600 0 +12}
    {1664636400 43200 1 +12}
    {1680361200 39600 0 +12}
    {1696086000 43200 1 +12}
    {1712415600 39600 0 +12}
    {1728140400 43200 1 +12}
    {1743865200 39600 0 +12}
    {1759590000 43200 1 +12}
    {1775314800 39600 0 +12}
    {1791039600 43200 1 +12}
    {1806764400 39600 0 +12}
    {1822489200 43200 1 +12}
    {1838214000 39600 0 +12}
    {1853938800 43200 1 +12}
    {1869663600 39600 0 +12}
    {1885993200 43200 1 +12}
    {1901718000 39600 0 +12}
    {1917442800 43200 1 +12}
    {1933167600 39600 0 +12}
    {1948892400 43200 1 +12}
    {1964617200 39600 0 +12}
    {1980342000 43200 1 +12}
    {1996066800 39600 0 +12}
    {2011791600 43200 1 +12}
    {2027516400 39600 0 +12}
    {2043241200 43200 1 +12}
    {2058966000 39600 0 +12}
    {2075295600 43200 1 +12}
    {2091020400 39600 0 +12}
    {2106745200 43200 1 +12}
    {2122470000 39600 0 +12}
    {2138194800 43200 1 +12}
    {2153919600 39600 0 +12}
    {2169644400 43200 1 +12}
    {2185369200 39600 0 +12}
    {2201094000 43200 1 +12}
    {2216818800 39600 0 +12}
    {2233148400 43200 1 +12}
    {2248873200 39600 0 +12}
    {2264598000 43200 1 +12}
    {2280322800 39600 0 +12}
    {2296047600 43200 1 +12}
    {2311772400 39600 0 +12}
    {2327497200 43200 1 +12}
    {2343222000 39600 0 +12}
    {2358946800 43200 1 +12}
    {2374671600 39600 0 +12}
    {2390396400 43200 1 +12}
    {2406121200 39600 0 +12}
    {2422450800 43200 1 +12}
    {2438175600 39600 0 +12}
    {2453900400 43200 1 +12}
    {2469625200 39600 0 +12}
    {2485350000 43200 1 +12}
    {2501074800 39600 0 +12}
    {2516799600 43200 1 +12}
    {2532524400 39600 0 +12}
    {2548249200 43200 1 +12}
    {2563974000 39600 0 +12}
    {2579698800 43200 1 +12}
    {2596028400 39600 0 +12}
    {2611753200 43200 1 +12}
    {2627478000 39600 0 +12}
    {2643202800 43200 1 +12}
    {2658927600 39600 0 +12}
    {2674652400 43200 1 +12}
    {2690377200 39600 0 +12}
    {2706102000 43200 1 +12}
    {2721826800 39600 0 +12}
    {2737551600 43200 1 +12}
    {2753276400 39600 0 +12}
    {2769606000 43200 1 +12}
    {2785330800 39600 0 +12}
    {2801055600 43200 1 +12}
    {2816780400 39600 0 +12}
    {2832505200 43200 1 +12}
    {2848230000 39600 0 +12}
    {2863954800 43200 1 +12}
    {2879679600 39600 0 +12}
    {2895404400 43200 1 +12}
    {2911129200 39600 0 +12}
    {2926854000 43200 1 +12}
    {2942578800 39600 0 +12}
    {2958908400 43200 1 +12}
    {2974633200 39600 0 +12}
    {2990358000 43200 1 +12}
    {3006082800 39600 0 +12}
    {3021807600 43200 1 +12}
    {3037532400 39600 0 +12}
    {3053257200 43200 1 +12}
    {3068982000 39600 0 +12}
    {3084706800 43200 1 +12}
    {3100431600 39600 0 +12}
    {3116761200 43200 1 +12}
    {3132486000 39600 0 +12}
    {3148210800 43200 1 +12}
    {3163935600 39600 0 +12}
    {3179660400 43200 1 +12}
    {3195385200 39600 0 +12}
    {3211110000 43200 1 +12}
    {3226834800 39600 0 +12}
    {3242559600 43200 1 +12}
    {3258284400 39600 0 +12}
    {3274009200 43200 1 +12}
    {3289734000 39600 0 +12}
    {3306063600 43200 1 +12}
    {3321788400 39600 0 +12}
    {3337513200 43200 1 +12}
    {3353238000 39600 0 +12}
    {3368962800 43200 1 +12}
    {3384687600 39600 0 +12}
    {3400412400 43200 1 +12}
    {3416137200 39600 0 +12}
    {3431862000 43200 1 +12}
    {3447586800 39600 0 +12}
    {3463311600 43200 1 +12}
    {3479641200 39600 0 +12}
    {3495366000 43200 1 +12}
    {3511090800 39600 0 +12}
    {3526815600 43200 1 +12}
    {3542540400 39600 0 +12}
    {3558265200 43200 1 +12}
    {3573990000 39600 0 +12}
    {3589714800 43200 1 +12}
    {3605439600 39600 0 +12}
    {3621164400 43200 1 +12}
    {3636889200 39600 0 +12}
    {3653218800 43200 1 +12}
    {3668943600 39600 0 +12}
    {3684668400 43200 1 +12}
    {3700393200 39600 0 +12}
    {3716118000 43200 1 +12}
    {3731842800 39600 0 +12}
    {3747567600 43200 1 +12}
    {3763292400 39600 0 +12}
    {3779017200 43200 1 +12}
    {3794742000 39600 0 +12}
    {3810466800 43200 1 +12}
    {3826191600 39600 0 +12}
    {3842521200 43200 1 +12}
    {3858246000 39600 0 +12}
    {3873970800 43200 1 +12}
    {3889695600 39600 0 +12}
    {3905420400 43200 1 +12}
    {3921145200 39600 0 +12}
    {3936870000 43200 1 +12}
    {3952594800 39600 0 +12}
    {3968319600 43200 1 +12}
    {3984044400 39600 0 +12}
    {4000374000 43200 1 +12}
    {4016098800 39600 0 +12}
    {4031823600 43200 1 +12}
    {4047548400 39600 0 +12}
    {4063273200 43200 1 +12}
    {4078998000 39600 0 +12}
    {4094722800 43200 1 +12}
}







|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

1
2
3
4
5
6
7
8
9


































































































































































10
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Norfolk) {
    {-9223372036854775808 40312 0 LMT}
    {-2177493112 40320 0 +1112}
    {-599656320 41400 0 +1130}
    {152029800 45000 1 +1230}
    {162912600 41400 0 +1130}
    {1443882600 39600 0 +11}


































































































































































}

Changes to library/tzdata/Pacific/Palau.

1
2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Palau) {
    {-9223372036854775808 -54124 0 LMT}
    {-3944624276 32276 0 LMT}
    {-2177485076 32400 0 +09}
}



|
<


1
2
3
4

5
6
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Palau) {
    {-9223372036854775808 32276 0 LMT}

    {-2177485076 32400 0 +09}
}

Changes to library/tzdata/Pacific/Pohnpei.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Guadalcanal)]} {
    LoadTimeZoneFile Pacific/Guadalcanal
}
set TZData(:Pacific/Pohnpei) $TZData(:Pacific/Guadalcanal)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Pohnpei) {
    {-9223372036854775808 37972 0 LMT}
    {-2177490772 39600 0 +11}
}

Changes to library/tzdata/Pacific/Ponape.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Guadalcanal)]} {
    LoadTimeZoneFile Pacific/Guadalcanal
}
set TZData(:Pacific/Ponape) $TZData(:Pacific/Guadalcanal)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Pohnpei)]} {
    LoadTimeZoneFile Pacific/Pohnpei
}
set TZData(:Pacific/Ponape) $TZData(:Pacific/Pohnpei)

Changes to library/tzdata/Pacific/Rarotonga.

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Rarotonga) {
    {-9223372036854775808 48056 0 LMT}
    {-2209555256 -38344 0 LMT}
    {-543072056 -37800 0 -1030}
    {279714600 -34200 0 -10}
    {289387800 -36000 0 -10}
    {309952800 -34200 1 -10}
    {320837400 -36000 0 -10}
    {341402400 -34200 1 -10}
    {352287000 -36000 0 -10}
    {372852000 -34200 1 -10}



|
<
|







1
2
3
4

5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Rarotonga) {
    {-9223372036854775808 -38344 0 LMT}

    {-2177414456 -37800 0 -1030}
    {279714600 -34200 0 -10}
    {289387800 -36000 0 -10}
    {309952800 -34200 1 -10}
    {320837400 -36000 0 -10}
    {341402400 -34200 1 -10}
    {352287000 -36000 0 -10}
    {372852000 -34200 1 -10}

Changes to library/tzdata/Pacific/Tongatapu.

1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tongatapu) {
    {-9223372036854775808 44352 0 LMT}
    {-767189952 44400 0 +1220}
    {-284041200 46800 0 +13}
    {915102000 46800 0 +13}
    {939214800 50400 1 +13}
    {953384400 46800 0 +13}
    {973342800 50400 1 +13}
    {980596800 46800 0 +13}
    {1004792400 50400 1 +13}
    {1012046400 46800 0 +13}



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tongatapu) {
    {-9223372036854775808 44360 0 LMT}
    {-2177497160 44400 0 +1220}
    {-915193200 46800 0 +13}
    {915102000 46800 0 +13}
    {939214800 50400 1 +13}
    {953384400 46800 0 +13}
    {973342800 50400 1 +13}
    {980596800 46800 0 +13}
    {1004792400 50400 1 +13}
    {1012046400 46800 0 +13}

Changes to library/tzdata/Pacific/Truk.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Pacific/Truk) $TZData(:Pacific/Port_Moresby)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
}
set TZData(:Pacific/Truk) $TZData(:Pacific/Chuuk)

Changes to library/tzdata/Pacific/Wake.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa
}
set TZData(:Pacific/Wake) $TZData(:Pacific/Tarawa)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Wake) {
    {-9223372036854775808 39988 0 LMT}
    {-2177492788 43200 0 +12}
}

Changes to library/tzdata/Pacific/Wallis.

1
2
3
4
5



# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa
}
set TZData(:Pacific/Wallis) $TZData(:Pacific/Tarawa)




<
<
|
|
>
>
>
1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Wallis) {
    {-9223372036854775808 44120 0 LMT}
    {-2177496920 43200 0 +12}
}

Changes to library/tzdata/Pacific/Yap.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Pacific/Yap) $TZData(:Pacific/Port_Moresby)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
}
set TZData(:Pacific/Yap) $TZData(:Pacific/Chuuk)

Changes to library/tzdata/UCT.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Etc/UTC)]} {
    LoadTimeZoneFile Etc/UTC
}
set TZData(:UCT) $TZData(:Etc/UTC)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Etc/UCT)]} {
    LoadTimeZoneFile Etc/UCT
}
set TZData(:UCT) $TZData(:Etc/UCT)

Added library/tzdata/US/Pacific-New.











>
>
>
>
>
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Los_Angeles)]} {
    LoadTimeZoneFile America/Los_Angeles
}
set TZData(:US/Pacific-New) $TZData(:America/Los_Angeles)

Added libtommath/bn.ilg.













>
>
>
>
>
>
1
2
3
4
5
6
This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
Scanning input file bn.idx....done (79 entries accepted, 0 rejected).
Sorting entries....done (511 comparisons).
Generating output file bn.ind....done (82 lines written, 0 warnings).
Output written in bn.ind.
Transcript written in bn.ilg.

Added libtommath/bn.ind.





































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
\begin{theindex}

  \item mp\_add, \hyperpage{29}
  \item mp\_add\_d, \hyperpage{52}
  \item mp\_and, \hyperpage{29}
  \item mp\_clear, \hyperpage{11}
  \item mp\_clear\_multi, \hyperpage{12}
  \item mp\_cmp, \hyperpage{24}
  \item mp\_cmp\_d, \hyperpage{25}
  \item mp\_cmp\_mag, \hyperpage{23}
  \item mp\_div, \hyperpage{30}
  \item mp\_div\_2, \hyperpage{26}
  \item mp\_div\_2d, \hyperpage{28}
  \item mp\_div\_d, \hyperpage{52}
  \item mp\_dr\_reduce, \hyperpage{40}
  \item mp\_dr\_setup, \hyperpage{40}
  \item MP\_EQ, \hyperpage{22}
  \item mp\_error\_to\_string, \hyperpage{10}
  \item mp\_expt\_d, \hyperpage{43}
  \item mp\_exptmod, \hyperpage{43}
  \item mp\_exteuclid, \hyperpage{51}
  \item mp\_gcd, \hyperpage{51}
  \item mp\_get\_int, \hyperpage{20}
  \item mp\_grow, \hyperpage{16}
  \item MP\_GT, \hyperpage{22}
  \item mp\_init, \hyperpage{11}
  \item mp\_init\_copy, \hyperpage{13}
  \item mp\_init\_multi, \hyperpage{12}
  \item mp\_init\_set, \hyperpage{21}
  \item mp\_init\_set\_int, \hyperpage{21}
  \item mp\_init\_size, \hyperpage{14}
  \item mp\_int, \hyperpage{10}
  \item mp\_invmod, \hyperpage{52}
  \item mp\_jacobi, \hyperpage{52}
  \item mp\_lcm, \hyperpage{51}
  \item mp\_lshd, \hyperpage{28}
  \item MP\_LT, \hyperpage{22}
  \item MP\_MEM, \hyperpage{9}
  \item mp\_mod, \hyperpage{35}
  \item mp\_mod\_d, \hyperpage{52}
  \item mp\_montgomery\_calc\_normalization, \hyperpage{38}
  \item mp\_montgomery\_reduce, \hyperpage{37}
  \item mp\_montgomery\_setup, \hyperpage{37}
  \item mp\_mul, \hyperpage{31}
  \item mp\_mul\_2, \hyperpage{26}
  \item mp\_mul\_2d, \hyperpage{28}
  \item mp\_mul\_d, \hyperpage{52}
  \item mp\_n\_root, \hyperpage{44}
  \item mp\_neg, \hyperpage{29}
  \item MP\_NO, \hyperpage{9}
  \item MP\_OKAY, \hyperpage{9}
  \item mp\_or, \hyperpage{29}
  \item mp\_prime\_fermat, \hyperpage{45}
  \item mp\_prime\_is\_divisible, \hyperpage{45}
  \item mp\_prime\_is\_prime, \hyperpage{46}
  \item mp\_prime\_miller\_rabin, \hyperpage{45}
  \item mp\_prime\_next\_prime, \hyperpage{46}
  \item mp\_prime\_rabin\_miller\_trials, \hyperpage{46}
  \item mp\_prime\_random, \hyperpage{47}
  \item mp\_prime\_random\_ex, \hyperpage{47}
  \item mp\_radix\_size, \hyperpage{49}
  \item mp\_read\_radix, \hyperpage{49}
  \item mp\_read\_unsigned\_bin, \hyperpage{50}
  \item mp\_reduce, \hyperpage{36}
  \item mp\_reduce\_2k, \hyperpage{41}
  \item mp\_reduce\_2k\_setup, \hyperpage{41}
  \item mp\_reduce\_setup, \hyperpage{36}
  \item mp\_rshd, \hyperpage{28}
  \item mp\_set, \hyperpage{19}
  \item mp\_set\_int, \hyperpage{20}
  \item mp\_shrink, \hyperpage{15}
  \item mp\_sqr, \hyperpage{33}
  \item mp\_sub, \hyperpage{29}
  \item mp\_sub\_d, \hyperpage{52}
  \item mp\_to\_unsigned\_bin, \hyperpage{50}
  \item mp\_toradix, \hyperpage{49}
  \item mp\_unsigned\_bin\_size, \hyperpage{50}
  \item MP\_VAL, \hyperpage{9}
  \item mp\_xor, \hyperpage{29}
  \item MP\_YES, \hyperpage{9}

\end{theindex}

Added libtommath/bn.pdf.

cannot compute difference between binary files

Added libtommath/bn.tex.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
\usepackage{color}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{layout}
\def\union{\cup}
\def\intersect{\cap}
\def\getsrandom{\stackrel{\rm R}{\gets}}
\def\cross{\times}
\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
\def\catn{$\|$}
\def\divides{\hspace{0.3em} | \hspace{0.3em}}
\def\nequiv{\not\equiv}
\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
\def\lcm{{\rm lcm}}
\def\gcd{{\rm gcd}}
\def\log{{\rm log}}
\def\ord{{\rm ord}}
\def\abs{{\mathit abs}}
\def\rep{{\mathit rep}}
\def\mod{{\mathit\ mod\ }}
\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
\def\Or{{\rm\ or\ }}
\def\And{{\rm\ and\ }}
\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
\def\implies{\Rightarrow}
\def\undefined{{\rm ``undefined"}}
\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
\let\oldphi\phi
\def\phi{\varphi}
\def\Pr{{\rm Pr}}
\newcommand{\str}[1]{{\mathbf{#1}}}
\def\F{{\mathbb F}}
\def\N{{\mathbb N}}
\def\Z{{\mathbb Z}}
\def\R{{\mathbb R}}
\def\C{{\mathbb C}}
\def\Q{{\mathbb Q}}
\definecolor{DGray}{gray}{0.5}
\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\frontmatter
\pagestyle{empty}
\title{LibTomMath User Manual \\ v0.39}
\author{Tom St Denis \\ [email protected]}
\maketitle
This text, the library and the accompanying textbook are all hereby placed in the public domain.  This book has been 
formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.

\vspace{10cm}

\begin{flushright}Open Source.  Open Academia.  Open Minds.

\mbox{ }

Tom St Denis,

Ontario, Canada
\end{flushright}

\tableofcontents
\listoffigures
\mainmatter
\pagestyle{headings}
\chapter{Introduction}
\section{What is LibTomMath?}
LibTomMath is a library of source code which provides a series of efficient and carefully written functions for manipulating
large integer numbers.  It was written in portable ISO C source code so that it will build on any platform with a conforming
C compiler.  

In a nutshell the library was written from scratch with verbose comments to help instruct computer science students how
to implement ``bignum'' math.  However, the resulting code has proven to be very useful.  It has been used by numerous 
universities, commercial and open source software developers.  It has been used on a variety of platforms ranging from
Linux and Windows based x86 to ARM based Gameboys and PPC based MacOS machines.  

\section{License}
As of the v0.25 the library source code has been placed in the public domain with every new release.  As of the v0.28
release the textbook ``Implementing Multiple Precision Arithmetic'' has been placed in the public domain with every new
release as well.  This textbook is meant to compliment the project by providing a more solid walkthrough of the development
algorithms used in the library.

Since both\footnote{Note that the MPI files under mtest/ are copyrighted by Michael Fromberger.  They are not required to use LibTomMath.} are in the 
public domain everyone is entitled to do with them as they see fit.

\section{Building LibTomMath}

LibTomMath is meant to be very ``GCC friendly'' as it comes with a makefile well suited for GCC.  However, the library will
also build in MSVC, Borland C out of the box.  For any other ISO C compiler a makefile will have to be made by the end
developer.  

\subsection{Static Libraries}
To build as a static library for GCC issue the following
\begin{alltt}
make
\end{alltt}

command.  This will build the library and archive the object files in ``libtommath.a''.  Now you link against 
that and include ``tommath.h'' within your programs.  Alternatively to build with MSVC issue the following
\begin{alltt}
nmake -f makefile.msvc
\end{alltt}

This will build the library and archive the object files in ``tommath.lib''.  This has been tested with MSVC 
version 6.00 with service pack 5.  

\subsection{Shared Libraries}
To build as a shared library for GCC issue the following
\begin{alltt}
make -f makefile.shared
\end{alltt}
This requires the ``libtool'' package (common on most Linux/BSD systems).  It will build LibTomMath as both shared
and static then install (by default) into /usr/lib as well as install the header files in /usr/include.  The shared 
library (resource) will be called ``libtommath.la'' while the static library called ``libtommath.a''.  Generally 
you use libtool to link your application against the shared object.  

There is limited support for making a ``DLL'' in windows via the ``makefile.cygwin\_dll'' makefile.  It requires 
Cygwin to work with since it requires the auto-export/import functionality.  The resulting DLL and import library 
``libtommath.dll.a'' can be used to link LibTomMath dynamically to any Windows program using Cygwin.

\subsection{Testing}
To build the library and the test harness type

\begin{alltt}
make test
\end{alltt}

This will build the library, ``test'' and ``mtest/mtest''.  The ``test'' program will accept test vectors and verify the
results.  ``mtest/mtest'' will generate test vectors using the MPI library by Michael Fromberger\footnote{A copy of MPI
is included in the package}.  Simply pipe mtest into test using

\begin{alltt}
mtest/mtest | test
\end{alltt}

If you do not have a ``/dev/urandom'' style RNG source you will have to write your own PRNG and simply pipe that into 
mtest.  For example, if your PRNG program is called ``myprng'' simply invoke

\begin{alltt}
myprng | mtest/mtest | test
\end{alltt}

This will output a row of numbers that are increasing.  Each column is a different test (such as addition, multiplication, etc)
that is being performed.  The numbers represent how many times the test was invoked.  If an error is detected the program
will exit with a dump of the relevent numbers it was working with.

\section{Build Configuration}
LibTomMath can configured at build time in three phases we shall call ``depends'', ``tweaks'' and ``trims''.  
Each phase changes how the library is built and they are applied one after another respectively.  

To make the system more powerful you can tweak the build process.  Classes are defined in the file
``tommath\_superclass.h''.  By default, the symbol ``LTM\_ALL'' shall be defined which simply 
instructs the system to build all of the functions.  This is how LibTomMath used to be packaged.  This will give you 
access to every function LibTomMath offers.

However, there are cases where such a build is not optional.  For instance, you want to perform RSA operations.  You 
don't need the vast majority of the library to perform these operations.  Aside from LTM\_ALL there is 
another pre--defined class ``SC\_RSA\_1'' which works in conjunction with the RSA from LibTomCrypt.  Additional 
classes can be defined base on the need of the user.

\subsection{Build Depends}
In the file tommath\_class.h you will see a large list of C ``defines'' followed by a series of ``ifdefs''
which further define symbols.  All of the symbols (technically they're macros $\ldots$) represent a given C source
file.  For instance, BN\_MP\_ADD\_C represents the file ``bn\_mp\_add.c''.  When a define has been enabled the
function in the respective file will be compiled and linked into the library.  Accordingly when the define
is absent the file will not be compiled and not contribute any size to the library.

You will also note that the header tommath\_class.h is actually recursively included (it includes itself twice).  
This is to help resolve as many dependencies as possible.  In the last pass the symbol LTM\_LAST will be defined.  
This is useful for ``trims''.

\subsection{Build Tweaks}
A tweak is an algorithm ``alternative''.  For example, to provide tradeoffs (usually between size and space).
They can be enabled at any pass of the configuration phase.

\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Define} & \textbf{Purpose} \\
\hline BN\_MP\_DIV\_SMALL & Enables a slower, smaller and equally \\
                          & functional mp\_div() function \\
\hline
\end{tabular}
\end{center}
\end{small}

\subsection{Build Trims}
A trim is a manner of removing functionality from a function that is not required.  For instance, to perform
RSA cryptography you only require exponentiation with odd moduli so even moduli support can be safely removed.  
Build trims are meant to be defined on the last pass of the configuration which means they are to be defined
only if LTM\_LAST has been defined.

\subsubsection{Moduli Related}
\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Restriction} & \textbf{Undefine} \\
\hline Exponentiation with odd moduli only & BN\_S\_MP\_EXPTMOD\_C \\
                                           & BN\_MP\_REDUCE\_C \\
                                           & BN\_MP\_REDUCE\_SETUP\_C \\
                                           & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
                                           & BN\_FAST\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
\hline Exponentiation with random odd moduli & (The above plus the following) \\
                                           & BN\_MP\_REDUCE\_2K\_C \\
                                           & BN\_MP\_REDUCE\_2K\_SETUP\_C \\
                                           & BN\_MP\_REDUCE\_IS\_2K\_C \\
                                           & BN\_MP\_DR\_IS\_MODULUS\_C \\
                                           & BN\_MP\_DR\_REDUCE\_C \\
                                           & BN\_MP\_DR\_SETUP\_C \\
\hline Modular inverse odd moduli only     & BN\_MP\_INVMOD\_SLOW\_C \\
\hline Modular inverse (both, smaller/slower) & BN\_FAST\_MP\_INVMOD\_C \\
\hline
\end{tabular}
\end{center}
\end{small}

\subsubsection{Operand Size Related}
\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Restriction} & \textbf{Undefine} \\
\hline Moduli $\le 2560$ bits              & BN\_MP\_MONTGOMERY\_REDUCE\_C \\
                                           & BN\_S\_MP\_MUL\_DIGS\_C \\
                                           & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
                                           & BN\_S\_MP\_SQR\_C \\
\hline Polynomial Schmolynomial            & BN\_MP\_KARATSUBA\_MUL\_C \\
                                           & BN\_MP\_KARATSUBA\_SQR\_C \\
                                           & BN\_MP\_TOOM\_MUL\_C \\ 
                                           & BN\_MP\_TOOM\_SQR\_C \\

\hline
\end{tabular}
\end{center}
\end{small}


\section{Purpose of LibTomMath}
Unlike  GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath was not written with 
bleeding edge performance in mind.  First and foremost LibTomMath was written to be entirely open.  Not only is the 
source code public domain (unlike various other GPL/etc licensed code), not only is the code freely downloadable but the
source code is also accessible for computer science students attempting to learn ``BigNum'' or multiple precision
arithmetic techniques. 

LibTomMath was written to be an instructive collection of source code.  This is why there are many comments, only one
function per source file and often I use a ``middle-road'' approach where I don't cut corners for an extra 2\% speed
increase.

Source code alone cannot really teach how the algorithms work which is why I also wrote a textbook that accompanies
the library (beat that!).

So you may be thinking ``should I use LibTomMath?'' and the answer is a definite maybe.  Let me tabulate what I think
are the pros and cons of LibTomMath by comparing it to the math routines from GnuPG\footnote{GnuPG v1.2.3 versus LibTomMath v0.28}.

\newpage\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|l|c|c|l|}
\hline \textbf{Criteria} & \textbf{Pro} & \textbf{Con} & \textbf{Notes} \\
\hline Few lines of code per file & X & & GnuPG $ = 300.9$, LibTomMath  $ = 71.97$ \\
\hline Commented function prototypes & X && GnuPG function names are cryptic. \\
\hline Speed && X & LibTomMath is slower.  \\
\hline Totally free & X & & GPL has unfavourable restrictions.\\
\hline Large function base & X & & GnuPG is barebones. \\
\hline Five modular reduction algorithms & X & & Faster modular exponentiation for a variety of moduli. \\
\hline Portable & X & & GnuPG requires configuration to build. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{LibTomMath Valuation}
\end{figure}

It may seem odd to compare LibTomMath to GnuPG since the math in GnuPG is only a small portion of the entire application. 
However, LibTomMath was written with cryptography in mind.  It provides essentially all of the functions a cryptosystem
would require when working with large integers.  

So it may feel tempting to just rip the math code out of GnuPG (or GnuMP where it was taken from originally) in your
own application but I think there are reasons not to.  While LibTomMath is slower than libraries such as GnuMP it is
not normally significantly slower.  On x86 machines the difference is normally a factor of two when performing modular
exponentiations.  It depends largely on the processor, compiler and the moduli being used.

Essentially the only time you wouldn't use LibTomMath is when blazing speed is the primary concern.  However,
on the other side of the coin LibTomMath offers you a totally free (public domain) well structured math library
that is very flexible, complete and performs well in resource contrained environments.  Fast RSA for example can
be performed with as little as 8KB of ram for data (again depending on build options).  

\chapter{Getting Started with LibTomMath}
\section{Building Programs}
In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library file (typically 
libtommath.a).  There is no library initialization required and the entire library is thread safe.

\section{Return Codes}
There are three possible return codes a function may return.

\index{MP\_OKAY}\index{MP\_YES}\index{MP\_NO}\index{MP\_VAL}\index{MP\_MEM}
\begin{figure}[here!]
\begin{center}
\begin{small}
\begin{tabular}{|l|l|}
\hline \textbf{Code} & \textbf{Meaning} \\
\hline MP\_OKAY & The function succeeded. \\
\hline MP\_VAL  & The function input was invalid. \\
\hline MP\_MEM  & Heap memory exhausted. \\
\hline &\\
\hline MP\_YES  & Response is yes. \\
\hline MP\_NO   & Response is no. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Return Codes}
\end{figure}

The last two codes listed are not actually ``return'ed'' by a function.  They are placed in an integer (the caller must
provide the address of an integer it can store to) which the caller can access.  To convert one of the three return codes
to a string use the following function.

\index{mp\_error\_to\_string}
\begin{alltt}
char *mp_error_to_string(int code);
\end{alltt}

This will return a pointer to a string which describes the given error code.  It will not work for the return codes 
MP\_YES and MP\_NO.  

\section{Data Types}
The basic ``multiple precision integer'' type is known as the ``mp\_int'' within LibTomMath.  This data type is used to
organize all of the data required to manipulate the integer it represents.  Within LibTomMath it has been prototyped
as the following.

\index{mp\_int}
\begin{alltt}
typedef struct  \{
    int used, alloc, sign;
    mp_digit *dp;
\} mp_int;
\end{alltt}

Where ``mp\_digit'' is a data type that represents individual digits of the integer.  By default, an mp\_digit is the
ISO C ``unsigned long'' data type and each digit is $28-$bits long.  The mp\_digit type can be configured to suit other
platforms by defining the appropriate macros.  

All LTM functions that use the mp\_int type will expect a pointer to mp\_int structure.  You must allocate memory to
hold the structure itself by yourself (whether off stack or heap it doesn't matter).  The very first thing that must be
done to use an mp\_int is that it must be initialized.

\section{Function Organization}

The arithmetic functions of the library are all organized to have the same style prototype.  That is source operands
are passed on the left and the destination is on the right.  For instance,

\begin{alltt}
mp_add(&a, &b, &c);       /* c = a + b */
mp_mul(&a, &a, &c);       /* c = a * a */
mp_div(&a, &b, &c, &d);   /* c = [a/b], d = a mod b */
\end{alltt}

Another feature of the way the functions have been implemented is that source operands can be destination operands as well.
For instance,

\begin{alltt}
mp_add(&a, &b, &b);       /* b = a + b */
mp_div(&a, &b, &a, &c);   /* a = [a/b], c = a mod b */
\end{alltt}

This allows operands to be re-used which can make programming simpler.

\section{Initialization}
\subsection{Single Initialization}
A single mp\_int can be initialized with the ``mp\_init'' function. 

\index{mp\_init}
\begin{alltt}
int mp_init (mp_int * a);
\end{alltt}

This function expects a pointer to an mp\_int structure and will initialize the members of the structure so the mp\_int
represents the default integer which is zero.  If the functions returns MP\_OKAY then the mp\_int is ready to be used
by the other LibTomMath functions.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Single Free}
When you are finished with an mp\_int it is ideal to return the heap it used back to the system.  The following function 
provides this functionality.

\index{mp\_clear}
\begin{alltt}
void mp_clear (mp_int * a);
\end{alltt}

The function expects a pointer to a previously initialized mp\_int structure and frees the heap it uses.  It sets the 
pointer\footnote{The ``dp'' member.} within the mp\_int to \textbf{NULL} which is used to prevent double free situations. 
Is is legal to call mp\_clear() twice on the same mp\_int in a row.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   /* We're done with it. */
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Multiple Initializations}
Certain algorithms require more than one large integer.  In these instances it is ideal to initialize all of the mp\_int
variables in an ``all or nothing'' fashion.  That is, they are either all initialized successfully or they are all
not initialized.

The  mp\_init\_multi() function provides this functionality.

\index{mp\_init\_multi} \index{mp\_clear\_multi}
\begin{alltt}
int mp_init_multi(mp_int *mp, ...);
\end{alltt}

It accepts a \textbf{NULL} terminated list of pointers to mp\_int structures.  It will attempt to initialize them all
at once.  If the function returns MP\_OKAY then all of the mp\_int variables are ready to use, otherwise none of them
are available for use.  A complementary mp\_clear\_multi() function allows multiple mp\_int variables to be free'd 
from the heap at the same time.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int num1, num2, num3;
   int result;

   if ((result = mp_init_multi(&num1, 
                               &num2,
                               &num3, NULL)) != MP\_OKAY) \{      
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the numbers */

   /* We're done with them. */
   mp_clear_multi(&num1, &num2, &num3, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Other Initializers}
To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided.  

\index{mp\_init\_copy}
\begin{alltt}
int mp_init_copy (mp_int * a, mp_int * b);
\end{alltt}

This function will initialize $a$ and make it a copy of $b$ if all goes well.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int num1, num2;
   int result;

   /* initialize and do work on num1 ... */

   /* We want a copy of num1 in num2 now */
   if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{
     printf("Error initializing the copy.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* now num2 is ready and contains a copy of num1 */

   /* We're done with them. */
   mp_clear_multi(&num1, &num2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

Another less common initializer is mp\_init\_size() which allows the user to initialize an mp\_int with a given
default number of digits.  By default, all initializers allocate \textbf{MP\_PREC} digits.  This function lets
you override this behaviour.

\index{mp\_init\_size}
\begin{alltt}
int mp_init_size (mp_int * a, int size);
\end{alltt}

The $size$ parameter must be greater than zero.  If the function succeeds the mp\_int $a$ will be initialized
to have $size$ digits (which are all initially zero).  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   /* we need a 60-digit number */
   if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\section{Maintenance Functions}

\subsection{Reducing Memory Usage}
When an mp\_int is in a state where it won't be changed again\footnote{A Diffie-Hellman modulus for instance.} excess
digits can be removed to return memory to the heap with the mp\_shrink() function.

\index{mp\_shrink}
\begin{alltt}
int mp_shrink (mp_int * a);
\end{alltt}

This will remove excess digits of the mp\_int $a$.  If the operation fails the mp\_int should be intact without the
excess digits being removed.  Note that you can use a shrunk mp\_int in further computations, however, such operations
will require heap operations which can be slow.  It is not ideal to shrink mp\_int variables that you will further
modify in the system (unless you are seriously low on memory).  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number [e.g. pre-computation]  */

   /* We're done with it for now. */
   if ((result = mp_shrink(&number)) != MP_OKAY) \{
      printf("Error shrinking the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* use it .... */


   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Adding additional digits}

Within the mp\_int structure are two parameters which control the limitations of the array of digits that represent
the integer the mp\_int is meant to equal.   The \textit{used} parameter dictates how many digits are significant, that is,
contribute to the value of the mp\_int.  The \textit{alloc} parameter dictates how many digits are currently available in
the array.  If you need to perform an operation that requires more digits you will have to mp\_grow() the mp\_int to
your desired size.  

\index{mp\_grow}
\begin{alltt}
int mp_grow (mp_int * a, int size);
\end{alltt}

This will grow the array of digits of $a$ to $size$.  If the \textit{alloc} parameter is already bigger than
$size$ the function will not do anything.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   /* We need to add 20 digits to the number  */
   if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{
      printf("Error growing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}


   /* use the number */

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\chapter{Basic Operations}
\section{Small Constants}
Setting mp\_ints to small constants is a relatively common operation.  To accomodate these instances there are two
small constant assignment functions.  The first function is used to set a single digit constant while the second sets
an ISO C style ``unsigned long'' constant.  The reason for both functions is efficiency.  Setting a single digit is quick but the
domain of a digit can change (it's always at least $0 \ldots 127$).  

\subsection{Single Digit}

Setting a single digit can be accomplished with the following function.

\index{mp\_set}
\begin{alltt}
void mp_set (mp_int * a, mp_digit b);
\end{alltt}

This will zero the contents of $a$ and make it represent an integer equal to the value of $b$.  Note that this
function has a return type of \textbf{void}.  It cannot cause an error so it is safe to assume the function
succeeded.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Long Constants}

To set a constant that is the size of an ISO C ``unsigned long'' and larger than a single digit the following function 
can be used.

\index{mp\_set\_int}
\begin{alltt}
int mp_set_int (mp_int * a, unsigned long b);
\end{alltt}

This will assign the value of the 32-bit variable $b$ to the mp\_int $a$.  Unlike mp\_set() this function will always
accept a 32-bit input regardless of the size of a single digit.  However, since the value may span several digits 
this function can fail if it runs out of heap memory.

To get the ``unsigned long'' copy of an mp\_int the following function can be used.

\index{mp\_get\_int}
\begin{alltt}
unsigned long mp_get_int (mp_int * a);
\end{alltt}

This will return the 32 least significant bits of the mp\_int $a$.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 654321 (note this is bigger than 127) */
   if ((result = mp_set_int(&number, 654321)) != MP_OKAY) \{
      printf("Error setting the value of the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   printf("number == \%lu", mp_get_int(&number));

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

This should output the following if the program succeeds.

\begin{alltt}
number == 654321
\end{alltt}

\subsection{Initialize and Setting Constants}
To both initialize and set small constants the following two functions are available.
\index{mp\_init\_set} \index{mp\_init\_set\_int}
\begin{alltt}
int mp_init_set (mp_int * a, mp_digit b);
int mp_init_set_int (mp_int * a, unsigned long b);
\end{alltt}

Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values.  

\begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int    result;

   /* initialize and set a single digit */
   if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{
      printf("Error setting number1: \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}             

   /* initialize and set a long */
   if ((result = mp_init_set_int(&number2, 1023)) != MP_OKAY) \{
      printf("Error setting number2: \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* display */
   printf("Number1, Number2 == \%lu, \%lu",
          mp_get_int(&number1), mp_get_int(&number2));

   /* clear */
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt}

If this program succeeds it shall output.
\begin{alltt}
Number1, Number2 == 100, 1023
\end{alltt}

\section{Comparisons}

Comparisons in LibTomMath are always performed in a ``left to right'' fashion.  There are three possible return codes
for any comparison.

\index{MP\_GT} \index{MP\_EQ} \index{MP\_LT}
\begin{figure}[here]
\begin{center}
\begin{tabular}{|c|c|}
\hline \textbf{Result Code} & \textbf{Meaning} \\
\hline MP\_GT & $a > b$ \\
\hline MP\_EQ & $a = b$ \\
\hline MP\_LT & $a < b$ \\
\hline
\end{tabular}
\end{center}
\caption{Comparison Codes for $a, b$}
\label{fig:CMP}
\end{figure}

In figure \ref{fig:CMP} two integers $a$ and $b$ are being compared.  In this case $a$ is said to be ``to the left'' of 
$b$.  

\subsection{Unsigned comparison}

An unsigned comparison considers only the digits themselves and not the associated \textit{sign} flag of the 
mp\_int structures.  This is analogous to an absolute comparison.  The function mp\_cmp\_mag() will compare two
mp\_int variables based on their digits only. 

\index{mp\_cmp\_mag}
\begin{alltt}
int mp_cmp_mag(mp_int * a, mp_int * b);
\end{alltt}
This will compare $a$ to $b$ placing $a$ to the left of $b$.  This function cannot fail and will return one of the
three compare codes listed in figure \ref{fig:CMP}.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number1 to 5 */
   mp_set(&number1, 5);
  
   /* set the number2 to -6 */
   mp_set(&number2, 6);
   if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
      printf("Error negating number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   switch(mp_cmp_mag(&number1, &number2)) \{
       case MP_GT:  printf("|number1| > |number2|"); break;
       case MP_EQ:  printf("|number1| = |number2|"); break;
       case MP_LT:  printf("|number1| < |number2|"); break;
   \}

   /* we're done with it. */ 
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes 
successfully it should print the following.

\begin{alltt}
|number1| < |number2|
\end{alltt}

This is because $\vert -6 \vert = 6$ and obviously $5 < 6$.

\subsection{Signed comparison}

To compare two mp\_int variables based on their signed value the mp\_cmp() function is provided.

\index{mp\_cmp}
\begin{alltt}
int mp_cmp(mp_int * a, mp_int * b);
\end{alltt}

This will compare $a$ to the left of $b$.  It will first compare the signs of the two mp\_int variables.  If they
differ it will return immediately based on their signs.  If the signs are equal then it will compare the digits
individually.  This function will return one of the compare conditions codes listed in figure \ref{fig:CMP}.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number1 to 5 */
   mp_set(&number1, 5);
  
   /* set the number2 to -6 */
   mp_set(&number2, 6);
   if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
      printf("Error negating number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   switch(mp_cmp(&number1, &number2)) \{
       case MP_GT:  printf("number1 > number2"); break;
       case MP_EQ:  printf("number1 = number2"); break;
       case MP_LT:  printf("number1 < number2"); break;
   \}

   /* we're done with it. */ 
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes 
successfully it should print the following.

\begin{alltt}
number1 > number2
\end{alltt}

\subsection{Single Digit}

To compare a single digit against an mp\_int the following function has been provided.

\index{mp\_cmp\_d}
\begin{alltt}
int mp_cmp_d(mp_int * a, mp_digit b);
\end{alltt}

This will compare $a$ to the left of $b$ using a signed comparison.  Note that it will always treat $b$ as 
positive.  This function is rather handy when you have to compare against small values such as $1$ (which often
comes up in cryptography).  The function cannot fail and will return one of the tree compare condition codes
listed in figure \ref{fig:CMP}.


\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("number > 7"); break;
       case MP_EQ:  printf("number = 7"); break;
       case MP_LT:  printf("number < 7"); break;
   \}

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program functions properly it will print out the following.

\begin{alltt}
number < 7
\end{alltt}

\section{Logical Operations}

Logical operations are operations that can be performed either with simple shifts or boolean operators such as
AND, XOR and OR directly.  These operations are very quick.

\subsection{Multiplication by two}

Multiplications and divisions by any power of two can be performed with quick logical shifts either left or
right depending on the operation.  

When multiplying or dividing by two a special case routine can be used which are as follows.
\index{mp\_mul\_2} \index{mp\_div\_2}
\begin{alltt}
int mp_mul_2(mp_int * a, mp_int * b);
int mp_div_2(mp_int * a, mp_int * b);
\end{alltt}

The former will assign twice $a$ to $b$ while the latter will assign half $a$ to $b$.  These functions are fast
since the shift counts and maskes are hardcoded into the routines.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   /* multiply by two */
   if ((result = mp\_mul\_2(&number, &number)) != MP_OKAY) \{
      printf("Error multiplying the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("2*number > 7"); break;
       case MP_EQ:  printf("2*number = 7"); break;
       case MP_LT:  printf("2*number < 7"); break;
   \}

   /* now divide by two */
   if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{
      printf("Error dividing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("2*number/2 > 7"); break;
       case MP_EQ:  printf("2*number/2 = 7"); break;
       case MP_LT:  printf("2*number/2 < 7"); break;
   \}

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program is successful it will print out the following text.

\begin{alltt}
2*number > 7
2*number/2 < 7
\end{alltt}

Since $10 > 7$ and $5 < 7$.  To multiply by a power of two the following function can be used.

\index{mp\_mul\_2d}
\begin{alltt}
int mp_mul_2d(mp_int * a, int b, mp_int * c);
\end{alltt}

This will multiply $a$ by $2^b$ and store the result in ``c''.  If the value of $b$ is less than or equal to 
zero the function will copy $a$ to ``c'' without performing any further actions.  

To divide by a power of two use the following.

\index{mp\_div\_2d}
\begin{alltt}
int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
\end{alltt}
Which will divide $a$ by $2^b$, store the quotient in ``c'' and the remainder in ``d'.  If $b \le 0$ then the
function simply copies $a$ over to ``c'' and zeroes $d$.  The variable $d$ may be passed as a \textbf{NULL}
value to signal that the remainder is not desired.

\subsection{Polynomial Basis Operations}

Strictly speaking the organization of the integers within the mp\_int structures is what is known as a 
``polynomial basis''.  This simply means a field element is stored by divisions of a radix.  For example, if
$f(x) = \sum_{i=0}^{k} y_ix^k$ for any vector $\vec y$ then the array of digits in $\vec y$ are said to be 
the polynomial basis representation of $z$ if $f(\beta) = z$ for a given radix $\beta$.  

To multiply by the polynomial $g(x) = x$ all you have todo is shift the digits of the basis left one place.  The
following function provides this operation.

\index{mp\_lshd}
\begin{alltt}
int mp_lshd (mp_int * a, int b);
\end{alltt}

This will multiply $a$ in place by $x^b$ which is equivalent to shifting the digits left $b$ places and inserting zeroes
in the least significant digits.  Similarly to divide by a power of $x$ the following function is provided.

\index{mp\_rshd}
\begin{alltt}
void mp_rshd (mp_int * a, int b)
\end{alltt}
This will divide $a$ in place by $x^b$ and discard the remainder.  This function cannot fail as it performs the operations
in place and no new digits are required to complete it.

\subsection{AND, OR and XOR Operations}

While AND, OR and XOR operations are not typical ``bignum functions'' they can be useful in several instances.  The
three functions are prototyped as follows.

\index{mp\_or} \index{mp\_and} \index{mp\_xor}
\begin{alltt}
int mp_or  (mp_int * a, mp_int * b, mp_int * c);
int mp_and (mp_int * a, mp_int * b, mp_int * c);
int mp_xor (mp_int * a, mp_int * b, mp_int * c);
\end{alltt}

Which compute $c = a \odot b$ where $\odot$ is one of OR, AND or XOR.  

\section{Addition and Subtraction}

To compute an addition or subtraction the following two functions can be used.

\index{mp\_add} \index{mp\_sub}
\begin{alltt}
int mp_add (mp_int * a, mp_int * b, mp_int * c);
int mp_sub (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}

Which perform $c = a \odot b$ where $\odot$ is one of signed addition or subtraction.  The operations are fully sign
aware.

\section{Sign Manipulation}
\subsection{Negation}
\label{sec:NEG}
Simple integer negation can be performed with the following.

\index{mp\_neg}
\begin{alltt}
int mp_neg (mp_int * a, mp_int * b);
\end{alltt}

Which assigns $-a$ to $b$.  

\subsection{Absolute}
Simple integer absolutes can be performed with the following.

\index{mp\_neg}
\begin{alltt}
int mp_abs (mp_int * a, mp_int * b);
\end{alltt}

Which assigns $\vert a \vert$ to $b$.  

\section{Integer Division and Remainder}
To perform a complete and general integer division with remainder use the following function.

\index{mp\_div}
\begin{alltt}
int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
\end{alltt}
                                                        
This divides $a$ by $b$ and stores the quotient in $c$ and $d$.  The signed quotient is computed such that 
$bc + d = a$.  Note that either of $c$ or $d$ can be set to \textbf{NULL} if their value is not required.  If 
$b$ is zero the function returns \textbf{MP\_VAL}.  


\chapter{Multiplication and Squaring}
\section{Multiplication}
A full signed integer multiplication can be performed with the following.
\index{mp\_mul}
\begin{alltt}
int mp_mul (mp_int * a, mp_int * b, mp_int * c);
\end{alltt}
Which assigns the full signed product $ab$ to $c$.  This function actually breaks into one of four cases which are 
specific multiplication routines optimized for given parameters.  First there are the Toom-Cook multiplications which
should only be used with very large inputs.  This is followed by the Karatsuba multiplications which are for moderate
sized inputs.  Then followed by the Comba and baseline multipliers.

Fortunately for the developer you don't really need to know this unless you really want to fine tune the system.  mp\_mul()
will determine on its own\footnote{Some tweaking may be required.} what routine to use automatically when it is called.

\begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   /* Initialize the numbers */
   if ((result = mp_init_multi(&number1, 
                               &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* set the terms */
   if ((result = mp_set_int(&number, 257)) != MP_OKAY) \{
      printf("Error setting number1.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   if ((result = mp_set_int(&number2, 1023)) != MP_OKAY) \{
      printf("Error setting number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* multiply them */
   if ((result = mp_mul(&number1, &number2,
                        &number1)) != MP_OKAY) \{
      printf("Error multiplying terms.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* display */
   printf("number1 * number2 == \%lu", mp_get_int(&number1));

   /* free terms and return */
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt}   

If this program succeeds it shall output the following.

\begin{alltt}
number1 * number2 == 262911
\end{alltt}

\section{Squaring}
Since squaring can be performed faster than multiplication it is performed it's own function instead of just using
mp\_mul().

\index{mp\_sqr}
\begin{alltt}
int mp_sqr (mp_int * a, mp_int * b);
\end{alltt}

Will square $a$ and store it in $b$.  Like the case of multiplication there are four different squaring
algorithms all which can be called from mp\_sqr().  It is ideal to use mp\_sqr over mp\_mul when squaring terms because
of the speed difference.  

\section{Tuning Polynomial Basis Routines}

Both of the Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that
the Comba and baseline algorithms use.  At $O(n^{1.464973})$ and $O(n^{1.584962})$ running times respectively they require 
considerably less work.  For example, a 10000-digit multiplication would take roughly 724,000 single precision
multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor
of 138).

So why not always use Karatsuba or Toom-Cook?   The simple answer is that they have so much overhead that they're not
actually faster than Comba until you hit distinct  ``cutoff'' points.  For Karatsuba with the default configuration, 
GCC 3.3.1 and an Athlon XP processor the cutoff point is roughly 110 digits (about 70 for the Intel P4).  That is, at 
110 digits Karatsuba and Comba multiplications just about break even and for 110+ digits Karatsuba is faster.

Toom-Cook has incredible overhead and is probably only useful for very large inputs.  So far no known cutoff points 
exist and for the most part I just set the cutoff points very high to make sure they're not called.

A demo program in the ``etc/'' directory of the project called ``tune.c'' can be used to find the cutoff points.  This
can be built with GCC as follows

\begin{alltt}
make XXX
\end{alltt}
Where ``XXX'' is one of the following entries from the table \ref{fig:tuning}.

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|l|l|}
\hline \textbf{Value of XXX} & \textbf{Meaning} \\
\hline tune & Builds portable tuning application \\
\hline tune86 & Builds x86 (pentium and up) program for COFF \\
\hline tune86c & Builds x86 program for Cygwin \\
\hline tune86l & Builds x86 program for Linux (ELF format) \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Build Names for Tuning Programs}
\label{fig:tuning}
\end{figure}

When the program is running it will output a series of measurements for different cutoff points.  It will first find
good Karatsuba squaring and multiplication points.  Then it proceeds to find Toom-Cook points.  Note that the Toom-Cook
tuning takes a very long time as the cutoff points are likely to be very high.

\chapter{Modular Reduction}

Modular reduction is process of taking the remainder of one quantity divided by another.  Expressed 
as (\ref{eqn:mod}) the modular reduction is equivalent to the remainder of $b$ divided by $c$.  

\begin{equation}
a \equiv b \mbox{ (mod }c\mbox{)}
\label{eqn:mod}
\end{equation}

Of particular interest to cryptography are reductions where $b$ is limited to the range $0 \le b < c^2$ since particularly 
fast reduction algorithms can be written for the limited range.  

Note that one of the four optimized reduction algorithms are automatically chosen in the modular exponentiation
algorithm mp\_exptmod when an appropriate modulus is detected.  

\section{Straight Division}
In order to effect an arbitrary modular reduction the following algorithm is provided.

\index{mp\_mod}
\begin{alltt}
int mp_mod(mp_int *a, mp_int *b, mp_int *c);
\end{alltt}

This reduces $a$ modulo $b$ and stores the result in $c$.  The sign of $c$ shall agree with the sign 
of $b$.  This algorithm accepts an input $a$ of any range and is not limited by $0 \le a < b^2$.

\section{Barrett Reduction}

Barrett reduction is a generic optimized reduction algorithm that requires pre--computation to achieve
a decent speedup over straight division.  First a $\mu$ value must be precomputed with the following function.

\index{mp\_reduce\_setup}
\begin{alltt}
int mp_reduce_setup(mp_int *a, mp_int *b);
\end{alltt}

Given a modulus in $b$ this produces the required $\mu$ value in $a$.  For any given modulus this only has to
be computed once.  Modular reduction can now be performed with the following.

\index{mp\_reduce}
\begin{alltt}
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
\end{alltt}

This will reduce $a$ in place modulo $b$ with the precomputed $\mu$ value in $c$.  $a$ must be in the range
$0 \le a < b^2$.

\begin{alltt}
int main(void)
\{
   mp_int   a, b, c, mu;
   int      result;

   /* initialize a,b to desired values, mp_init mu, 
    * c and set c to 1...we want to compute a^3 mod b 
    */

   /* get mu value */
   if ((result = mp_reduce_setup(&mu, b)) != MP_OKAY) \{
      printf("Error getting mu.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* square a to get c = a^2 */
   if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
      printf("Error squaring.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' modulo b */
   if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* multiply a to get c = a^3 */
   if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' modulo b  */
   if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
  
   /* c now equals a^3 mod b */

   return EXIT_SUCCESS;
\}
\end{alltt} 

This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed.  

\section{Montgomery Reduction}

Montgomery is a specialized reduction algorithm for any odd moduli.  Like Barrett reduction a pre--computation
step is required.  This is accomplished with the following.

\index{mp\_montgomery\_setup}
\begin{alltt}
int mp_montgomery_setup(mp_int *a, mp_digit *mp);
\end{alltt}

For the given odd moduli $a$ the precomputation value is placed in $mp$.  The reduction is computed with the 
following.

\index{mp\_montgomery\_reduce}
\begin{alltt}
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
\end{alltt}
This reduces $a$ in place modulo $m$ with the pre--computed value $mp$.   $a$ must be in the range
$0 \le a < b^2$.

Montgomery reduction is faster than Barrett reduction for moduli smaller than the ``comba'' limit.  With the default
setup for instance, the limit is $127$ digits ($3556$--bits).   Note that this function is not limited to
$127$ digits just that it falls back to a baseline algorithm after that point.  

An important observation is that this reduction does not return $a \mbox{ mod }m$ but $aR^{-1} \mbox{ mod }m$ 
where $R = \beta^n$, $n$ is the n number of digits in $m$ and $\beta$ is radix used (default is $2^{28}$).  

To quickly calculate $R$ the following function was provided.

\index{mp\_montgomery\_calc\_normalization}
\begin{alltt}
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
\end{alltt}
Which calculates $a = R$ for the odd moduli $b$ without using multiplication or division.  

The normal modus operandi for Montgomery reductions is to normalize the integers before entering the system.  For
example, to calculate $a^3 \mbox { mod }b$ using Montgomery reduction the value of $a$ can be normalized by
multiplying it by $R$.  Consider the following code snippet.

\begin{alltt}
int main(void)
\{
   mp_int   a, b, c, R;
   mp_digit mp;
   int      result;

   /* initialize a,b to desired values, 
    * mp_init R, c and set c to 1.... 
    */

   /* get normalization */
   if ((result = mp_montgomery_calc_normalization(&R, b)) != MP_OKAY) \{
      printf("Error getting norm.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* get mp value */
   if ((result = mp_montgomery_setup(&c, &mp)) != MP_OKAY) \{
      printf("Error setting up montgomery.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* normalize `a' so now a is equal to aR */
   if ((result = mp_mulmod(&a, &R, &b, &a)) != MP_OKAY) \{
      printf("Error computing aR.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* square a to get c = a^2R^2 */
   if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
      printf("Error squaring.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' back down to c = a^2R^2 * R^-1 == a^2R */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* multiply a to get c = a^3R^2 */
   if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' back down to c = a^3R^2 * R^-1 == a^3R */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* now reduce (again) `c' back down to c = a^3R * R^-1 == a^3 */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* c now equals a^3 mod b */

   return EXIT_SUCCESS;
\}
\end{alltt} 

This particular example does not look too efficient but it demonstrates the point of the algorithm.  By 
normalizing the inputs the reduced results are always of the form $aR$ for some variable $a$.  This allows
a single final reduction to correct for the normalization and the fast reduction used within the algorithm.

For more details consider examining the file \textit{bn\_mp\_exptmod\_fast.c}.

\section{Restricted Dimminished Radix}

``Dimminished Radix'' reduction refers to reduction with respect to moduli that are ameniable to simple
digit shifting and small multiplications.  In this case the ``restricted'' variant refers to moduli of the
form $\beta^k - p$ for some $k \ge 0$ and $0 < p < \beta$ where $\beta$ is the radix (default to $2^{28}$).  

As in the case of Montgomery reduction there is a pre--computation phase required for a given modulus.

\index{mp\_dr\_setup}
\begin{alltt}
void mp_dr_setup(mp_int *a, mp_digit *d);
\end{alltt}

This computes the value required for the modulus $a$ and stores it in $d$.  This function cannot fail
and does not return any error codes.  After the pre--computation a reduction can be performed with the
following.

\index{mp\_dr\_reduce}
\begin{alltt}
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
\end{alltt}

This reduces $a$ in place modulo $b$ with the pre--computed value $mp$.  $b$ must be of a restricted
dimminished radix form and $a$ must be in the range $0 \le a < b^2$.  Dimminished radix reductions are 
much faster than both Barrett and Montgomery reductions as they have a much lower asymtotic running time.  

Since the moduli are restricted this algorithm is not particularly useful for something like Rabin, RSA or
BBS cryptographic purposes.  This reduction algorithm is useful for Diffie-Hellman and ECC where fixed
primes are acceptable.  

Note that unlike Montgomery reduction there is no normalization process.  The result of this function is
equal to the correct residue.

\section{Unrestricted Dimminshed Radix}

Unrestricted reductions work much like the restricted counterparts except in this case the moduli is of the 
form $2^k - p$ for $0 < p < \beta$.  In this sense the unrestricted reductions are more flexible as they 
can be applied to a wider range of numbers.  

\index{mp\_reduce\_2k\_setup}
\begin{alltt}
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
\end{alltt}

This will compute the required $d$ value for the given moduli $a$.  

\index{mp\_reduce\_2k}
\begin{alltt}
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
\end{alltt}

This will reduce $a$ in place modulo $n$ with the pre--computed value $d$.  From my experience this routine is 
slower than mp\_dr\_reduce but faster for most moduli sizes than the Montgomery reduction.  

\chapter{Exponentiation}
\section{Single Digit Exponentiation}
\index{mp\_expt\_d}
\begin{alltt}
int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
\end{alltt}
This computes $c = a^b$ using a simple binary left-to-right algorithm.  It is faster than repeated multiplications by 
$a$ for all values of $b$ greater than three.  

\section{Modular Exponentiation}
\index{mp\_exptmod}
\begin{alltt}
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
\end{alltt}
This computes $Y \equiv G^X \mbox{ (mod }P\mbox{)}$ using a variable width sliding window algorithm.  This function
will automatically detect the fastest modular reduction technique to use during the operation.  For negative values of 
$X$ the operation is performed as $Y \equiv (G^{-1} \mbox{ mod }P)^{\vert X \vert} \mbox{ (mod }P\mbox{)}$ provided that 
$gcd(G, P) = 1$.

This function is actually a shell around the two internal exponentiation functions.  This routine will automatically
detect when Barrett, Montgomery, Restricted and Unrestricted Dimminished Radix based exponentiation can be used.  Generally
moduli of the a ``restricted dimminished radix'' form lead to the fastest modular exponentiations.  Followed by Montgomery
and the other two algorithms.

\section{Root Finding}
\index{mp\_n\_root}
\begin{alltt}
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
\end{alltt}
This computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$.  The implementation of this function is not 
ideal for values of $b$ greater than three.  It will work but become very slow.  So unless you are working with very small
numbers (less than 1000 bits) I'd avoid $b > 3$ situations.  Will return a positive root only for even roots and return
a root with the sign of the input for odd roots.  For example, performing $4^{1/2}$ will return $2$ whereas $(-8)^{1/3}$ 
will return $-2$.  

This algorithm uses the ``Newton Approximation'' method and will converge on the correct root fairly quickly.  Since
the algorithm requires raising $a$ to the power of $b$ it is not ideal to attempt to find roots for large
values of $b$.  If particularly large roots are required then a factor method could be used instead.  For example,
$a^{1/16}$ is equivalent to $\left (a^{1/4} \right)^{1/4}$ or simply 
$\left ( \left ( \left ( a^{1/2} \right )^{1/2} \right )^{1/2} \right )^{1/2}$

\chapter{Prime Numbers}
\section{Trial Division}
\index{mp\_prime\_is\_divisible}
\begin{alltt}
int mp_prime_is_divisible (mp_int * a, int *result)
\end{alltt}
This will attempt to evenly divide $a$ by a list of primes\footnote{Default is the first 256 primes.} and store the 
outcome in ``result''.  That is if $result = 0$ then $a$ is not divisible by the primes, otherwise it is.  Note that 
if the function does not return \textbf{MP\_OKAY} the value in ``result'' should be considered undefined\footnote{Currently
the default is to set it to zero first.}.

\section{Fermat Test}
\index{mp\_prime\_fermat}
\begin{alltt}
int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
\end{alltt}
Performs a Fermat primality test to the base $b$.  That is it computes $b^a \mbox{ mod }a$ and tests whether the value is
equal to $b$ or not.  If the values are equal then $a$ is probably prime and $result$ is set to one.  Otherwise $result$
is set to zero.

\section{Miller-Rabin Test}
\index{mp\_prime\_miller\_rabin}
\begin{alltt}
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
\end{alltt}
Performs a Miller-Rabin test to the base $b$ of $a$.  This test is much stronger than the Fermat test and is very hard to
fool (besides with Carmichael numbers).  If $a$ passes the test (therefore is probably prime) $result$ is set to one.  
Otherwise $result$ is set to zero.  

Note that is suggested that you use the Miller-Rabin test instead of the Fermat test since all of the failures of 
Miller-Rabin are a subset of the failures of the Fermat test.

\subsection{Required Number of Tests}
Generally to ensure a number is very likely to be prime you have to perform the Miller-Rabin with at least a half-dozen
or so unique bases.  However, it has been proven that the probability of failure goes down as the size of the input goes up.
This is why a simple function has been provided to help out.

\index{mp\_prime\_rabin\_miller\_trials}
\begin{alltt}
int mp_prime_rabin_miller_trials(int size)
\end{alltt}
This returns the number of trials required for a $2^{-96}$ (or lower) probability of failure for a given ``size'' expressed
in bits.  This comes in handy specially since larger numbers are slower to test.  For example, a 512-bit number would
require ten tests whereas a 1024-bit number would only require four tests. 

You should always still perform a trial division before a Miller-Rabin test though.

\section{Primality Testing}
\index{mp\_prime\_is\_prime}
\begin{alltt}
int mp_prime_is_prime (mp_int * a, int t, int *result)
\end{alltt}
This will perform a trial division followed by $t$ rounds of Miller-Rabin tests on $a$ and store the result in $result$.  
If $a$ passes all of the tests $result$ is set to one, otherwise it is set to zero.  Note that $t$ is bounded by 
$1 \le t < PRIME\_SIZE$ where $PRIME\_SIZE$ is the number of primes in the prime number table (by default this is $256$).

\section{Next Prime}
\index{mp\_prime\_next\_prime}
\begin{alltt}
int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
\end{alltt}
This finds the next prime after $a$ that passes mp\_prime\_is\_prime() with $t$ tests.  Set $bbs\_style$ to one if you 
want only the next prime congruent to $3 \mbox{ mod } 4$, otherwise set it to zero to find any next prime.  

\section{Random Primes}
\index{mp\_prime\_random}
\begin{alltt}
int mp_prime_random(mp_int *a, int t, int size, int bbs, 
                    ltm_prime_callback cb, void *dat)
\end{alltt}
This will find a prime greater than $256^{size}$ which can be ``bbs\_style'' or not depending on $bbs$ and must pass
$t$ rounds of tests.  The ``ltm\_prime\_callback'' is a typedef for 

\begin{alltt}
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
\end{alltt}

Which is a function that must read $len$ bytes (and return the amount stored) into $dst$.  The $dat$ variable is simply
copied from the original input.  It can be used to pass RNG context data to the callback.  The function 
mp\_prime\_random() is more suitable for generating primes which must be secret (as in the case of RSA) since there 
is no skew on the least significant bits.

\textit{Note:}  As of v0.30 of the LibTomMath library this function has been deprecated.  It is still available
but users are encouraged to use the new mp\_prime\_random\_ex() function instead.

\subsection{Extended Generation}
\index{mp\_prime\_random\_ex}
\begin{alltt}
int mp_prime_random_ex(mp_int *a,    int t, 
                       int     size, int flags, 
                       ltm_prime_callback cb, void *dat);
\end{alltt}
This will generate a prime in $a$ using $t$ tests of the primality testing algorithms.  The variable $size$
specifies the bit length of the prime desired.  The variable $flags$ specifies one of several options available
(see fig. \ref{fig:primeopts}) which can be OR'ed together.  The callback parameters are used as in 
mp\_prime\_random().

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|r|l|}
\hline \textbf{Flag}         & \textbf{Meaning} \\
\hline LTM\_PRIME\_BBS       & Make the prime congruent to $3$ modulo $4$ \\
\hline LTM\_PRIME\_SAFE      & Make a prime $p$ such that $(p - 1)/2$ is also prime. \\
                             & This option implies LTM\_PRIME\_BBS as well. \\
\hline LTM\_PRIME\_2MSB\_OFF & Makes sure that the bit adjacent to the most significant bit \\
                             & Is forced to zero.  \\
\hline LTM\_PRIME\_2MSB\_ON  & Makes sure that the bit adjacent to the most significant bit \\
                             & Is forced to one. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Primality Generation Options}
\label{fig:primeopts}
\end{figure}

\chapter{Input and Output}
\section{ASCII Conversions}
\subsection{To ASCII}
\index{mp\_toradix}
\begin{alltt}
int mp_toradix (mp_int * a, char *str, int radix);
\end{alltt}
This still store $a$ in ``str'' as a base-``radix'' string of ASCII chars.  This function appends a NUL character
to terminate the string.  Valid values of ``radix'' line in the range $[2, 64]$.  To determine the size (exact) required
by the conversion before storing any data use the following function.

\index{mp\_radix\_size}
\begin{alltt}
int mp_radix_size (mp_int * a, int radix, int *size)
\end{alltt}
This stores in ``size'' the number of characters (including space for the NUL terminator) required.  Upon error this 
function returns an error code and ``size'' will be zero.  

\subsection{From ASCII}
\index{mp\_read\_radix}
\begin{alltt}
int mp_read_radix (mp_int * a, char *str, int radix);
\end{alltt}
This will read the base-``radix'' NUL terminated string from ``str'' into $a$.  It will stop reading when it reads a
character it does not recognize (which happens to include th NUL char... imagine that...).  A single leading $-$ sign
can be used to denote a negative number.

\section{Binary Conversions}

Converting an mp\_int to and from binary is another keen idea.

\index{mp\_unsigned\_bin\_size}
\begin{alltt}
int mp_unsigned_bin_size(mp_int *a);
\end{alltt}

This will return the number of bytes (octets) required to store the unsigned copy of the integer $a$.

\index{mp\_to\_unsigned\_bin}
\begin{alltt}
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
\end{alltt}
This will store $a$ into the buffer $b$ in big--endian format.  Fortunately this is exactly what DER (or is it ASN?)
requires.  It does not store the sign of the integer.

\index{mp\_read\_unsigned\_bin}
\begin{alltt}
int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
\end{alltt}
This will read in an unsigned big--endian array of bytes (octets) from $b$ of length $c$ into $a$.  The resulting
integer $a$ will always be positive.

For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' versions of the
previous functions.

\begin{alltt}
int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a, unsigned char *b);
\end{alltt}
They operate essentially the same as the unsigned copies except they prefix the data with zero or non--zero
byte depending on the sign.  If the sign is zpos (e.g. not negative) the prefix is zero, otherwise the prefix
is non--zero.  

\chapter{Algebraic Functions}
\section{Extended Euclidean Algorithm}
\index{mp\_exteuclid}
\begin{alltt}
int mp_exteuclid(mp_int *a, mp_int *b, 
                 mp_int *U1, mp_int *U2, mp_int *U3);
\end{alltt}

This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that the following equation holds.

\begin{equation}
a \cdot U1 + b \cdot U2 = U3
\end{equation}

Any of the U1/U2/U3 paramters can be set to \textbf{NULL} if they are not desired.  

\section{Greatest Common Divisor}
\index{mp\_gcd}
\begin{alltt}
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
This will compute the greatest common divisor of $a$ and $b$ and store it in $c$.

\section{Least Common Multiple}
\index{mp\_lcm}
\begin{alltt}
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
This will compute the least common multiple of $a$ and $b$ and store it in $c$.

\section{Jacobi Symbol}
\index{mp\_jacobi}
\begin{alltt}
int mp_jacobi (mp_int * a, mp_int * p, int *c)
\end{alltt}
This will compute the Jacobi symbol for $a$ with respect to $p$.  If $p$ is prime this essentially computes the Legendre
symbol.  The result is stored in $c$ and can take on one of three values $\lbrace -1, 0, 1 \rbrace$.  If $p$ is prime
then the result will be $-1$ when $a$ is not a quadratic residue modulo $p$.  The result will be $0$ if $a$ divides $p$
and the result will be $1$ if $a$ is a quadratic residue modulo $p$.  

\section{Modular Inverse}
\index{mp\_invmod}
\begin{alltt}
int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
Computes the multiplicative inverse of $a$ modulo $b$ and stores the result in $c$ such that $ac \equiv 1 \mbox{ (mod }b\mbox{)}$.

\section{Single Digit Functions}

For those using small numbers (\textit{snicker snicker}) there are several ``helper'' functions

\index{mp\_add\_d} \index{mp\_sub\_d} \index{mp\_mul\_d} \index{mp\_div\_d} \index{mp\_mod\_d}
\begin{alltt}
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
\end{alltt}

These work like the full mp\_int capable variants except the second parameter $b$ is a mp\_digit.  These
functions fairly handy if you have to work with relatively small numbers since you will not have to allocate
an entire mp\_int to store a number like $1$ or $2$.

\input{bn.ind}

\end{document}

Changes to libtommath/bn_fast_s_mp_mul_digs.c.

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;
    tmpc = c->dp;
    for (ix = 0; ix < pa; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;







|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;
    tmpc = c->dp;
    for (ix = 0; ix < pa+1; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;

Changes to libtommath/bn_mp_and.c.

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
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement and */
mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c)
{


   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = ((a->sign == MP_NEG) && (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {
         return err;

      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;



      /* convert to two complement if negative */
      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }



      c->dp[i] = x & y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }




   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif


|
<
|
>
|
<
<
>
>
|
|
>
>
|
<
|
<
|
<
>
|
<
|
<
|
>
|
>
|
<
<
<
<
<
<
|
>
>
>
|
<
<
|
|
<
|
>
|
|
>
>
|
<

<
|
<
|
<
|
|
>
>
>
|
|
<
|
>
>
|


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
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.


 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstde[email protected], http://math.libtomcrypt.com

 */


/* AND two ints together */

int
mp_and (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }



  for (ix = 0; ix < px; ix++) {

    t.dp[ix] &= x->dp[ix];

  }

  /* zero digits above the last from the smallest mp_int */
  for (; ix < t.used; ix++) {
    t.dp[ix] = 0;
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

Changes to libtommath/bn_mp_cmp.c.

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
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */














/* compare two ints (signed)*/

mp_ord mp_cmp(const mp_int *a, const mp_int *b)
{
   /* compare based on sign */
   if (a->sign != b->sign) {
      if (a->sign == MP_NEG) {
         return MP_LT;
      } else {
         return MP_GT;
      }
   }

   /* compare digits */
   if (a->sign == MP_NEG) {
      /* if negative compare opposite direction */
      return mp_cmp_mag(b, a);
   } else {
      return mp_cmp_mag(a, b);
   }
}
#endif


|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


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
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare two ints (signed)*/
int
mp_cmp (mp_int * a, mp_int * b)
{
  /* compare based on sign */
  if (a->sign != b->sign) {
     if (a->sign == MP_NEG) {
        return MP_LT;
     } else {
        return MP_GT;
     }
  }
  
  /* compare digits */
  if (a->sign == MP_NEG) {
     /* if negative compare opposite direction */
     return mp_cmp_mag(b, a);
  } else {
     return mp_cmp_mag(a, b);
  }
}
#endif

Changes to libtommath/bn_mp_cmp_d.c.

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
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */














/* compare a digit */
mp_ord mp_cmp_d(const mp_int *a, mp_digit b)
{
   /* compare based on sign */
   if (a->sign == MP_NEG) {
      return MP_LT;
   }

   /* compare based on magnitude */
   if (a->used > 1) {
      return MP_GT;
   }

   /* compare the only digit of a to b */
   if (a->dp[0] > b) {
      return MP_GT;
   } else if (a->dp[0] < b) {
      return MP_LT;
   } else {
      return MP_EQ;
   }
}
#endif


|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|


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
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare a digit */
int mp_cmp_d(mp_int * a, mp_digit b)
{
  /* compare based on sign */
  if (a->sign == MP_NEG) {
    return MP_LT;
  }

  /* compare based on magnitude */
  if (a->used > 1) {
    return MP_GT;
  }

  /* compare the only digit of a to b */
  if (a->dp[0] > b) {
    return MP_GT;
  } else if (a->dp[0] < b) {
    return MP_LT;
  } else {
    return MP_EQ;
  }
}
#endif

Changes to libtommath/bn_mp_cmp_mag.c.

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
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */














/* compare maginitude of two ints (unsigned) */
mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b)
{
   int     n;
   const mp_digit *tmpa, *tmpb;

   /* compare based on # of non-zero digits */
   if (a->used > b->used) {
      return MP_GT;
   }

   if (a->used < b->used) {
      return MP_LT;
   }

   /* alias for a */
   tmpa = a->dp + (a->used - 1);

   /* alias for b */
   tmpb = b->dp + (a->used - 1);

   /* compare based on digits  */
   for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
      if (*tmpa > *tmpb) {
         return MP_GT;
      }

      if (*tmpa < *tmpb) {
         return MP_LT;
      }
   }
   return MP_EQ;
}
#endif


|
<
>
>
>
>
>
>
>
>
>
>
>
>
>


|

|
|

|
|
|
|
|
|
|
|

|
|

|
|

|
|
|
|
|

|
|
|
|
|


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
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare maginitude of two ints (unsigned) */
int mp_cmp_mag (mp_int * a, mp_int * b)
{
  int     n;
  mp_digit *tmpa, *tmpb;

  /* compare based on # of non-zero digits */
  if (a->used > b->used) {
    return MP_GT;
  }
  
  if (a->used < b->used) {
    return MP_LT;
  }

  /* alias for a */
  tmpa = a->dp + (a->used - 1);

  /* alias for b */
  tmpb = b->dp + (a->used - 1);

  /* compare based on digits  */
  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
    if (*tmpa > *tmpb) {
      return MP_GT;
    }

    if (*tmpa < *tmpb) {
      return MP_LT;
    }
  }
  return MP_EQ;
}
#endif

Changes to libtommath/bn_mp_or.c.

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
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement or */
mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c)
{


   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = ((a->sign == MP_NEG) || (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {
         return err;

      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;


      /* convert to two complement if negative */
      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }

      c->dp[i] = x | y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }



   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif


|
<
|
>
|
<
<
>
>
|
|
>
>
|
<
|
<
|
<
>
|
<
|
|
<
|
>
|
<
<
<
<
<
<
|
>
>
>
|
<
<
|
|
<
|
>
|
|
|
<
|
<
<
<
<
<
|
|
>
>
|
<
<
|
>
>
|


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
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.


 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstde[email protected], http://math.libtomcrypt.com

 */


/* OR two ints together */
int mp_or (mp_int * a, mp_int * b, mp_int * c)

{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;

    x = a;





  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] |= x->dp[ix];
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

Changes to libtommath/bn_mp_xor.c.

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
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */


/* two complement xor */
mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c)
{


   int used = MAX(a->used, b->used) + 1, i;
   mp_err err;


   mp_digit ac = 1, bc = 1, cc = 1;
   mp_sign csign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;

   if (c->alloc < used) {
      if ((err = mp_grow(c, used)) != MP_OKAY) {
         return err;

      }
   }

   for (i = 0; i < used; i++) {
      mp_digit x, y;



      /* convert to two complement if negative */
      if (a->sign == MP_NEG) {
         ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
         x = ac & MP_MASK;
         ac >>= MP_DIGIT_BIT;
      } else {
         x = (i >= a->used) ? 0uL : a->dp[i];
      }




      /* convert to two complement if negative */
      if (b->sign == MP_NEG) {
         bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
         y = bc & MP_MASK;
         bc >>= MP_DIGIT_BIT;
      } else {

         y = (i >= b->used) ? 0uL : b->dp[i];
      }

      c->dp[i] = x ^ y;

      /* convert to to sign-magnitude if negative */
      if (csign == MP_NEG) {
         cc += ~c->dp[i] & MP_MASK;
         c->dp[i] = cc & MP_MASK;
         cc >>= MP_DIGIT_BIT;
      }
   }



   c->used = used;
   c->sign = csign;
   mp_clamp(c);


   return MP_OKAY;
}
#endif


|
<
|
>
|
<
<
>
>
|
|
>
>
|
<
|
<
|
<
>
|
<
|
<
|
>
|
>
|
<
<
<
<
<
<
|
>
>
>
|
<
<
|
|
<
|
>
|
|
|
<
|
<
<
<
<
<
|
|
>
>
|
<
<
|
>
>
|


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
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.


 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.

 *

 * Tom St Denis, tomstde[email protected], http://math.libtomcrypt.com

 */


/* XOR two ints together */

int
mp_xor (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;







  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }


    px = b->used;
    x = b;

  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;

    x = a;





  }

  for (ix = 0; ix < px; ix++) {
     t.dp[ix] ^= x->dp[ix];
  }


  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

Added libtommath/booker.pl.



















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/bin/perl
#
#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file
#
#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put
#
#EXAM,file
#
#This preprocessor will then open "file" and insert it as a verbatim copy.
#
#Tom St Denis

#get graphics type
if (shift =~ /PDF/) {
   $graph = "";
} else {
   $graph = ".ps";
}   

open(IN,"<tommath.src") or die "Can't open source file";
open(OUT,">tommath.tex") or die "Can't open destination file";

print "Scanning for sections\n";
$chapter = $section = $subsection = 0;
$x = 0;
while (<IN>) {
   print ".";
   if (!(++$x % 80)) { print "\n"; }
   #update the headings 
   if (~($_ =~ /\*/)) {
      if ($_ =~ /\\chapter{.+}/) {
          ++$chapter;
          $section = $subsection = 0;
      } elsif ($_ =~ /\\section{.+}/) {
          ++$section;
          $subsection = 0;
      } elsif ($_ =~ /\\subsection{.+}/) {
          ++$subsection;
      }
   }      

   if ($_ =~ m/MARK/) {
      @m = split(",",$_);
      chomp(@m[1]);
      $index1{@m[1]} = $chapter;
      $index2{@m[1]} = $section;
      $index3{@m[1]} = $subsection;
   }
}
close(IN);

open(IN,"<tommath.src") or die "Can't open source file";
$readline = $wroteline = 0;
$srcline = 0;

while (<IN>) {
   ++$readline;
   ++$srcline;
   
   if ($_ =~ m/MARK/) {
   } elsif ($_ =~ m/EXAM/ || $_ =~ m/LIST/) {
      if ($_ =~ m/EXAM/) {
         $skipheader = 1;
      } else {
         $skipheader = 0;
      }
      
      # EXAM,file
      chomp($_);
      @m = split(",",$_);
      open(SRC,"<$m[1]") or die "Error:$srcline:Can't open source file $m[1]";
      
      print "$srcline:Inserting $m[1]:";
      
      $line = 0;
      $tmp = $m[1];
      $tmp =~ s/_/"\\_"/ge;
      print OUT "\\vspace{+3mm}\\begin{small}\n\\hspace{-5.1mm}{\\bf File}: $tmp\n\\vspace{-3mm}\n\\begin{alltt}\n";
      $wroteline += 5;
      
      if ($skipheader == 1) {
         # scan till next end of comment, e.g. skip license 
         while (<SRC>) {
            $text[$line++] = $_;
            last if ($_ =~ /math\.libtomcrypt\.org/);
         }
         <SRC>;   
      }
      
      $inline = 0;
      while (<SRC>) {
      next if ($_ =~ /\$Source/);
      next if ($_ =~ /\$Revision/);
      next if ($_ =~ /\$Date/);
         $text[$line++] = $_;
         ++$inline;
         chomp($_);
         $_ =~ s/\t/"    "/ge;
         $_ =~ s/{/"^{"/ge;
         $_ =~ s/}/"^}"/ge;
         $_ =~ s/\\/'\symbol{92}'/ge;
         $_ =~ s/\^/"\\"/ge;
           
         printf OUT ("%03d   ", $line);
         for ($x = 0; $x < length($_); $x++) {
             print OUT chr(vec($_, $x, 8));
             if ($x == 75) { 
                 print OUT "\n      ";
                 ++$wroteline;
             }
         }
         print OUT "\n";
         ++$wroteline;
      }
      $totlines = $line;
      print OUT "\\end{alltt}\n\\end{small}\n";
      close(SRC);
      print "$inline lines\n";
      $wroteline += 2;
   } elsif ($_ =~ m/@\d+,.+@/) {
     # line contains [number,text]
     # e.g. @14,for (ix = 0)@
     $txt = $_;
     while ($txt =~ m/@\d+,.+@/) {
        @m = split("@",$txt);      # splits into text, one, two
        @parms = split(",",$m[1]);  # splits one,two into two elements 
                
        # now search from $parms[0] down for $parms[1] 
        $found1 = 0;
        $found2 = 0;
        for ($i = $parms[0]; $i < $totlines && $found1 == 0; $i++) {
           if ($text[$i] =~ m/\Q$parms[1]\E/) {
              $foundline1 = $i + 1;
              $found1 = 1;
           }
        }
        
        # now search backwards
        for ($i = $parms[0] - 1; $i >= 0 && $found2 == 0; $i--) {
           if ($text[$i] =~ m/\Q$parms[1]\E/) {
              $foundline2 = $i + 1;
              $found2 = 1;
           }
        }
        
        # now use the closest match or the first if tied
        if ($found1 == 1 && $found2 == 0) {
           $found = 1;
           $foundline = $foundline1;
        } elsif ($found1 == 0 && $found2 == 1) {
           $found = 1;
           $foundline = $foundline2;
        } elsif ($found1 == 1 && $found2 == 1) {
           $found = 1;
           if (($foundline1 - $parms[0]) <= ($parms[0] - $foundline2)) {
              $foundline = $foundline1;
           } else {
              $foundline = $foundline2;
           }
        } else {
           $found = 0;
        }
                      
        # if found replace 
        if ($found == 1) {
           $delta = $parms[0] - $foundline;
           print "Found replacement tag for \"$parms[1]\" on line $srcline which refers to line $foundline (delta $delta)\n";
           $_ =~ s/@\Q$m[1]\E@/$foundline/;
        } else {
           print "ERROR:  The tag \"$parms[1]\" on line $srcline was not found in the most recently parsed source!\n";
        }
        
        # remake the rest of the line 
        $cnt = @m;
        $txt = "";
        for ($i = 2; $i < $cnt; $i++) {
            $txt = $txt . $m[$i] . "@";
        }
     }
     print OUT $_;
     ++$wroteline;
   } elsif ($_ =~ /~.+~/) {
      # line contains a ~text~ pair used to refer to indexing :-)
      $txt = $_;
      while ($txt =~ /~.+~/) {
         @m = split("~", $txt);
         
         # word is the second position
         $word = @m[1];
         $a = $index1{$word};
         $b = $index2{$word};
         $c = $index3{$word};
         
         # if chapter (a) is zero it wasn't found
         if ($a == 0) {
            print "ERROR: the tag \"$word\" on line $srcline was not found previously marked.\n";
         } else {
            # format the tag as x, x.y or x.y.z depending on the values
            $str = $a;
            $str = $str . ".$b" if ($b != 0);
            $str = $str . ".$c" if ($c != 0);
            
            if ($b == 0 && $c == 0) {
               # its a chapter
               if ($a <= 10) {
                  if ($a == 1) {
                     $str = "chapter one";
                  } elsif ($a == 2) {
                     $str = "chapter two";
                  } elsif ($a == 3) {
                     $str = "chapter three";
                  } elsif ($a == 4) {
                     $str = "chapter four";
                  } elsif ($a == 5) {
                     $str = "chapter five";
                  } elsif ($a == 6) {
                     $str = "chapter six";
                  } elsif ($a == 7) {
                     $str = "chapter seven";
                  } elsif ($a == 8) {
                     $str = "chapter eight";
                  } elsif ($a == 9) {
                     $str = "chapter nine";
                  } elsif ($a == 10) {
                     $str = "chapter ten";
                  }
               } else {
                  $str = "chapter " . $str;
               }
            } else {
               $str = "section " . $str     if ($b != 0 && $c == 0);            
               $str = "sub-section " . $str if ($b != 0 && $c != 0);
            }
            
            #substitute
            $_ =~ s/~\Q$word\E~/$str/;
            
            print "Found replacement tag for marker \"$word\" on line $srcline which refers to $str\n";
         }
         
         # remake rest of the line
         $cnt = @m;
         $txt = "";
         for ($i = 2; $i < $cnt; $i++) {
             $txt = $txt . $m[$i] . "~";
         }
      }
      print OUT $_;
      ++$wroteline;
   } elsif ($_ =~ m/FIGU/) {
      # FIGU,file,caption
      chomp($_);
      @m = split(",", $_);
      print OUT "\\begin{center}\n\\begin{figure}[here]\n\\includegraphics{pics/$m[1]$graph}\n";
      print OUT "\\caption{$m[2]}\n\\label{pic:$m[1]}\n\\end{figure}\n\\end{center}\n";
      $wroteline += 4;
   } else {
      print OUT $_;
      ++$wroteline;
   }
}
print "Read $readline lines, wrote $wroteline lines\n";

close (OUT);
close (IN);

Added libtommath/callgraph.txt.

more than 10,000 changes

Added libtommath/demo/demo.c.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
#include <time.h>

#ifdef IOWNANATHLON
#include <unistd.h>
#define SLEEP sleep(4)
#else
#define SLEEP
#endif

#include "tommath.h"

void ndraw(mp_int * a, char *name)
{
   char buf[16000];

   printf("%s: ", name);
   mp_toradix(a, buf, 10);
   printf("%s\n", buf);
}

static void draw(mp_int * a)
{
   ndraw(a, "");
}


unsigned long lfsr = 0xAAAAAAAAUL;

int lbit(void)
{
   if (lfsr & 0x80000000UL) {
      lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
      return 1;
   } else {
      lfsr <<= 1;
      return 0;
   }
}

int myrng(unsigned char *dst, int len, void *dat)
{
   int x;

   for (x = 0; x < len; x++)
      dst[x] = rand() & 0xFF;
   return len;
}



char cmd[4096], buf[4096];
int main(void)
{
   mp_int a, b, c, d, e, f;
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
   unsigned rr;
   int i, n, err, cnt, ix, old_kara_m, old_kara_s;
   mp_digit mp;


   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));

#if 0
   // test montgomery 
   printf("Testing montgomery...\n");
   for (i = 1; i < 10; i++) {
      printf("Testing digit size: %d\n", i);
      for (n = 0; n < 1000; n++) {
         mp_rand(&a, i);
         a.dp[0] |= 1;

         // let's see if R is right
         mp_montgomery_calc_normalization(&b, &a);
         mp_montgomery_setup(&a, &mp);

         // now test a random reduction 
         for (ix = 0; ix < 100; ix++) {
             mp_rand(&c, 1 + abs(rand()) % (2*i));
             mp_copy(&c, &d);
             mp_copy(&c, &e);

             mp_mod(&d, &a, &d);
             mp_montgomery_reduce(&c, &a, mp);
             mp_mulmod(&c, &b, &a, &c);

             if (mp_cmp(&c, &d) != MP_EQ) { 
printf("d = e mod a, c = e MOD a\n");
mp_todecimal(&a, buf); printf("a = %s\n", buf);
mp_todecimal(&e, buf); printf("e = %s\n", buf);
mp_todecimal(&d, buf); printf("d = %s\n", buf);
mp_todecimal(&c, buf); printf("c = %s\n", buf);
printf("compare no compare!\n"); exit(EXIT_FAILURE); }
         }
      }
   }
   printf("done\n");

   // test mp_get_int
   printf("Testing: mp_get_int\n");
   for (i = 0; i < 1000; ++i) {
      t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
      mp_set_int(&a, t);
      if (t != mp_get_int(&a)) {
	 printf("mp_get_int() bad result!\n");
	 return 1;
      }
   }
   mp_set_int(&a, 0);
   if (mp_get_int(&a) != 0) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   mp_set_int(&a, 0xffffffff);
   if (mp_get_int(&a) != 0xffffffff) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   // test mp_sqrt
   printf("Testing: mp_sqrt\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);
      n = (rand() & 15) + 1;
      mp_rand(&a, n);
      if (mp_sqrt(&a, &b) != MP_OKAY) {
	 printf("mp_sqrt() error!\n");
	 return 1;
      }
      mp_n_root(&a, 2, &a);
      if (mp_cmp_mag(&b, &a) != MP_EQ) {
	 printf("mp_sqrt() bad result!\n");
	 return 1;
      }
   }

   printf("\nTesting: mp_is_square\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);

      /* test mp_is_square false negatives */
      n = (rand() & 7) + 1;
      mp_rand(&a, n);
      mp_sqr(&a, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fn:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 0) {
	 printf("fn:mp_is_square() bad result!\n");
	 return 1;
      }

      /* test for false positives */
      mp_add_d(&a, 1, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fp:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 1) {
	 printf("fp:mp_is_square() bad result!\n");
	 return 1;
      }

   }
   printf("\n\n");

   /* test for size */
   for (ix = 10; ix < 128; ix++) {
      printf("Testing (not safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    (rand() & 1) ? LTM_PRIME_2MSB_OFF :
			    LTM_PRIME_2MSB_ON, myrng, NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
   }

   for (ix = 16; ix < 128; ix++) {
      printf("Testing (   safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
			     LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
			    NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
      /* let's see if it's really a safe prime */
      mp_sub_d(&a, 1, &a);
      mp_div_2(&a, &a);
      mp_prime_is_prime(&a, 8, &cnt);
      if (cnt != MP_YES) {
	 printf("sub is not prime!\n");
	 return EXIT_FAILURE;
      }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("testing mp_cnt_lsb...\n");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
      if (mp_cnt_lsb(&a) != ix) {
	 printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
	 return 0;
      }
      mp_mul_2(&a, &a);
   }

/* test mp_reduce_2k */
   printf("Testing mp_reduce_2k...\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
      mp_digit tmp;

      mp_2expt(&a, cnt);
      mp_sub_d(&a, 2, &a);	/* a = 2**cnt - 2 */


      printf("\nTesting %4d bits", cnt);
      printf("(%d)", mp_reduce_is_2k(&a));
      mp_reduce_2k_setup(&a, &tmp);
      printf("(%d)", tmp);
      for (ix = 0; ix < 1000; ix++) {
	 if (!(ix & 127)) {
	    printf(".");
	    fflush(stdout);
	 }
	 mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
	 mp_copy(&c, &b);
	 mp_mod(&c, &a, &c);
	 mp_reduce_2k(&b, &a, 2);
	 if (mp_cmp(&c, &b)) {
	    printf("FAILED\n");
	    exit(0);
	 }
      }
   }

/* test mp_div_3  */
   printf("Testing mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000;) {
      mp_digit r1, r2;

      if (!(++cnt & 127))
	 printf("%9d\r", cnt);
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
	 printf("\n\nmp_div_3 => Failure\n");
      }
   }
   printf("\n\nPassed div_3 testing\n");

/* test the DR reduction */
   printf("testing mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
      printf("%d digit modulus\n", cnt);
      mp_grow(&a, cnt);
      mp_zero(&a);
      for (ix = 1; ix < cnt; ix++) {
	 a.dp[ix] = MP_MASK;
      }
      a.used = cnt;
      a.dp[0] = 3;

      mp_rand(&b, cnt - 1);
      mp_copy(&b, &c);

      rr = 0;
      do {
	 if (!(rr & 127)) {
	    printf("%9lu\r", rr);
	    fflush(stdout);
	 }
	 mp_sqr(&b, &b);
	 mp_add_d(&b, 1, &b);
	 mp_copy(&b, &c);

	 mp_mod(&b, &a, &b);
	 mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);

	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("Failed on trial %lu\n", rr);
	    exit(-1);

	 }
      } while (++rr < 500);
      printf("Passed DR test for %d digits\n", cnt);
   }

#endif

/* test the mp_reduce_2k_l code */
#if 0
#if 0
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
   mp_2expt(&a, 1024);
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
   mp_sub(&a, &b, &a);
#elif 1
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
   mp_2expt(&a, 2048);
   mp_read_radix(&b,
		 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
		 16);
   mp_sub(&a, &b, &a);
#endif

   mp_todecimal(&a, buf);
   printf("p==%s\n", buf);
/* now mp_reduce_is_2k_l() should return */
   if (mp_reduce_is_2k_l(&a) != 1) {
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
      return EXIT_FAILURE;
   }
   mp_reduce_2k_setup_l(&a, &d);
   /* now do a million square+1 to see if it varies */
   mp_rand(&b, 64);
   mp_mod(&b, &a, &b);
   mp_copy(&b, &c);
   printf("testing mp_reduce_2k_l...");
   fflush(stdout);
   for (cnt = 0; cnt < (1UL << 20); cnt++) {
      mp_sqr(&b, &b);
      mp_add_d(&b, 1, &b);
      mp_reduce_2k_l(&b, &a, &d);
      mp_sqr(&c, &c);
      mp_add_d(&c, 1, &c);
      mp_mod(&c, &a, &c);
      if (mp_cmp(&b, &c) != MP_EQ) {
	 printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
	 mp_tohex(&b, buf);
	 printf("b == %s\n", buf);
	 mp_tohex(&c, buf);
	 printf("c == %s\n", buf);
	 return EXIT_FAILURE;
      }
   }
   printf("...Passed\n");
#endif

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
      sub_d_n = 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

   for (;;) {
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
      switch (abs(rand()) % 7) {
      case 0:
	 mp_clear(&a);
	 mp_init(&a);
	 break;
      case 1:
	 mp_clear(&b);
	 mp_init(&b);
	 break;
      case 2:
	 mp_clear(&c);
	 mp_init(&c);
	 break;
      case 3:
	 mp_clear(&d);
	 mp_init(&d);
	 break;
      case 4:
	 mp_clear(&e);
	 mp_init(&e);
	 break;
      case 5:
	 mp_clear(&f);
	 mp_init(&f);
	 break;
      case 6:
	 break;			/* don't clear any */
      }


      printf
	 ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
	  add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
	  expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
      fgets(cmd, 4095, stdin);
      cmd[strlen(cmd) - 1] = 0;
      printf("%s  ]\r", cmd);
      fflush(stdout);
      if (!strcmp(cmd, "mul2d")) {
	 ++mul2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_mul_2d(&a, rr, &a);
	 a.sign = b.sign;
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("mul2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div2d")) {
	 ++div2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_div_2d(&a, rr, &a, &e);
	 a.sign = b.sign;
	 if (a.used == b.used && a.used == 0) {
	    a.sign = b.sign = MP_ZPOS;
	 }
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("div2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add")) {
	 ++add_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_add(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("add %lu failure!\n", add_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

	 /* test the sign/unsigned storage functions */

	 rr = mp_signed_bin_size(&c);
	 mp_to_signed_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mp_signed_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }


	 rr = mp_unsigned_bin_size(&c);
	 mp_to_unsigned_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp_mag(&c, &d) != MP_EQ) {
	    printf("mp_unsigned_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sub")) {
	 ++sub_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_sub(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("sub %lu failure!\n", sub_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul")) {
	 ++mul_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_mul(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mul %lu failure!\n", mul_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div")) {
	 ++div_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);

	 mp_div(&a, &b, &e, &f);
	 if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
	    printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
		   mp_cmp(&d, &f));
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    draw(&f);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sqr")) {
	 ++sqr_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_copy(&a, &c);
	 mp_sqr(&c, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sqr %lu failure!\n", sqr_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "gcd")) {
	 ++gcd_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_gcd(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("gcd %lu failure!\n", gcd_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "lcm")) {
	 ++lcm_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_lcm(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("lcm %lu failure!\n", lcm_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "expt")) {
	 ++expt_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);
	 mp_copy(&a, &e);
	 mp_exptmod(&e, &b, &c, &e);
	 if (mp_cmp(&d, &e) != MP_EQ) {
	    printf("expt %lu failure!\n", expt_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    return 0;
	 }
      } else if (!strcmp(cmd, "invmod")) {
	 ++inv_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_invmod(&a, &b, &d);
	 mp_mulmod(&d, &a, &b, &e);
	 if (mp_cmp_d(&e, 1) != MP_EQ) {
	    printf("inv [wrong value from MPI?!] failure\n");
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    mp_gcd(&a, &b, &e);
	    draw(&e);
	    return 0;
	 }

      } else if (!strcmp(cmd, "div2")) {
	 ++div2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_div_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("div_2 %lu failure\n", div2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul2")) {
	 ++mul2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_mul_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("mul_2 %lu failure\n", mul2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add_d")) {
	 ++add_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_add_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("add_d %lu failure\n", add_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      } else if (!strcmp(cmd, "sub_d")) {
	 ++sub_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_sub_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sub_d %lu failure\n", sub_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      }
   }
   return 0;
}

Added libtommath/demo/timing.c.























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#include <tommath.h>
#include <time.h>

ulong64 _tt;

#ifdef IOWNANATHLON
#include <unistd.h>
#define SLEEP sleep(4)
#else
#define SLEEP
#endif


void ndraw(mp_int * a, char *name)
{
   char buf[4096];

   printf("%s: ", name);
   mp_toradix(a, buf, 64);
   printf("%s\n", buf);
}

static void draw(mp_int * a)
{
   ndraw(a, "");
}


unsigned long lfsr = 0xAAAAAAAAUL;

int lbit(void)
{
   if (lfsr & 0x80000000UL) {
      lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
      return 1;
   } else {
      lfsr <<= 1;
      return 0;
   }
}

/* RDTSC from Scott Duplichan */
static ulong64 TIMFUNC(void)
{
#if defined __GNUC__
#if defined(__i386__) || defined(__x86_64__)
   unsigned long long a;
   __asm__ __volatile__("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::
			"m"(a):"%eax", "%edx");
   return a;
#else /* gcc-IA64 version */
   unsigned long result;
   __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory");

   while (__builtin_expect((int) result == -1, 0))
      __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory");

   return result;
#endif

   // Microsoft and Intel Windows compilers
#elif defined _M_IX86
   __asm rdtsc
#elif defined _M_AMD64
   return __rdtsc();
#elif defined _M_IA64
#if defined __INTEL_COMPILER
#include <ia64intrin.h>
#endif
   return __getReg(3116);
#else
#error need rdtsc function for this build
#endif
}

#define DO(x) x; x;
//#define DO4(x) DO2(x); DO2(x);
//#define DO8(x) DO4(x); DO4(x);
//#define DO(x)  DO8(x); DO8(x);

int main(void)
{
   ulong64 tt, gg, CLK_PER_SEC;
   FILE *log, *logb, *logc, *logd;
   mp_int a, b, c, d, e, f;
   int n, cnt, ix, old_kara_m, old_kara_s;
   unsigned rr;

   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));


   /* temp. turn off TOOM */
   TOOM_MUL_CUTOFF = TOOM_SQR_CUTOFF = 100000;

   CLK_PER_SEC = TIMFUNC();
   sleep(1);
   CLK_PER_SEC = TIMFUNC() - CLK_PER_SEC;

   printf("CLK_PER_SEC == %llu\n", CLK_PER_SEC);
   goto exptmod;
   log = fopen("logs/add.log", "w");
   for (cnt = 8; cnt <= 128; cnt += 8) {
      SLEEP;
      mp_rand(&a, cnt);
      mp_rand(&b, cnt);
      rr = 0;
      tt = -1;
      do {
	 gg = TIMFUNC();
	 DO(mp_add(&a, &b, &c));
	 gg = (TIMFUNC() - gg) >> 1;
	 if (tt > gg)
	    tt = gg;
      } while (++rr < 100000);
      printf("Adding\t\t%4d-bit => %9llu/sec, %9llu cycles\n",
	     mp_count_bits(&a), CLK_PER_SEC / tt, tt);
      fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
      fflush(log);
   }
   fclose(log);

   log = fopen("logs/sub.log", "w");
   for (cnt = 8; cnt <= 128; cnt += 8) {
      SLEEP;
      mp_rand(&a, cnt);
      mp_rand(&b, cnt);
      rr = 0;
      tt = -1;
      do {
	 gg = TIMFUNC();
	 DO(mp_sub(&a, &b, &c));
	 gg = (TIMFUNC() - gg) >> 1;
	 if (tt > gg)
	    tt = gg;
      } while (++rr < 100000);

      printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu cycles\n",
	     mp_count_bits(&a), CLK_PER_SEC / tt, tt);
      fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
      fflush(log);
   }
   fclose(log);

   /* do mult/square twice, first without karatsuba and second with */
 multtest:
   old_kara_m = KARATSUBA_MUL_CUTOFF;
   old_kara_s = KARATSUBA_SQR_CUTOFF;
   for (ix = 0; ix < 2; ix++) {
      printf("With%s Karatsuba\n", (ix == 0) ? "out" : "");

      KARATSUBA_MUL_CUTOFF = (ix == 0) ? 9999 : old_kara_m;
      KARATSUBA_SQR_CUTOFF = (ix == 0) ? 9999 : old_kara_s;

      log = fopen((ix == 0) ? "logs/mult.log" : "logs/mult_kara.log", "w");
      for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) {
	 SLEEP;
	 mp_rand(&a, cnt);
	 mp_rand(&b, cnt);
	 rr = 0;
	 tt = -1;
	 do {
	    gg = TIMFUNC();
	    DO(mp_mul(&a, &b, &c));
	    gg = (TIMFUNC() - gg) >> 1;
	    if (tt > gg)
	       tt = gg;
	 } while (++rr < 100);
	 printf("Multiplying\t%4d-bit => %9llu/sec, %9llu cycles\n",
		mp_count_bits(&a), CLK_PER_SEC / tt, tt);
	 fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);
	 fflush(log);
      }
      fclose(log);

      log = fopen((ix == 0) ? "logs/sqr.log" : "logs/sqr_kara.log", "w");
      for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) {
	 SLEEP;
	 mp_rand(&a, cnt);
	 rr = 0;
	 tt = -1;
	 do {
	    gg = TIMFUNC();
	    DO(mp_sqr(&a, &b));
	    gg = (TIMFUNC() - gg) >> 1;
	    if (tt > gg)
	       tt = gg;
	 } while (++rr < 100);
	 printf("Squaring\t%4d-bit => %9llu/sec, %9llu cycles\n",
		mp_count_bits(&a), CLK_PER_SEC / tt, tt);
	 fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);
	 fflush(log);
      }
      fclose(log);

   }
 exptmod:

   {
      char *primes[] = {
	 /* 2K large moduli */
	 "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586239334100047359817950870678242457666208137217",
	 "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638099733077152121140120031150424541696791951097529546801429027668869927491725169",
	 "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085902995208257421855249796721729039744118165938433694823325696642096892124547425283",
	 /* 2K moduli mersenne primes */
	 "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151",
	 "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127",
	 "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087",
	 "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007",
	 "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071",
	 "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991",

	 /* DR moduli */
	 "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079",
	 "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039",
	 "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431",
	 "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783",
	 "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147",
	 "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503",
	 "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679",

	 /* generic unrestricted moduli */
	 "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203",
	 "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487",
	 "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319",
	 "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887",
	 "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227",
	 "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207",
	 "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979",
	 NULL
      };
      log = fopen("logs/expt.log", "w");
      logb = fopen("logs/expt_dr.log", "w");
      logc = fopen("logs/expt_2k.log", "w");
      logd = fopen("logs/expt_2kl.log", "w");
      for (n = 0; primes[n]; n++) {
	 SLEEP;
	 mp_read_radix(&a, primes[n], 10);
	 mp_zero(&b);
	 for (rr = 0; rr < (unsigned) mp_count_bits(&a); rr++) {
	    mp_mul_2(&b, &b);
	    b.dp[0] |= lbit();
	    b.used += 1;
	 }
	 mp_sub_d(&a, 1, &c);
	 mp_mod(&b, &c, &b);
	 mp_set(&c, 3);
	 rr = 0;
	 tt = -1;
	 do {
	    gg = TIMFUNC();
	    DO(mp_exptmod(&c, &b, &a, &d));
	    gg = (TIMFUNC() - gg) >> 1;
	    if (tt > gg)
	       tt = gg;
	 } while (++rr < 10);
	 mp_sub_d(&a, 1, &e);
	 mp_sub(&e, &b, &b);
	 mp_exptmod(&c, &b, &a, &e);	/* c^(p-1-b) mod a */
	 mp_mulmod(&e, &d, &a, &d);	/* c^b * c^(p-1-b) == c^p-1 == 1 */
	 if (mp_cmp_d(&d, 1)) {
	    printf("Different (%d)!!!\n", mp_count_bits(&a));
	    draw(&d);
	    exit(0);
	 }
	 printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu cycles\n",
		mp_count_bits(&a), CLK_PER_SEC / tt, tt);
	 fprintf(n < 4 ? logd : (n < 9) ? logc : (n < 16) ? logb : log,
		 "%d %9llu\n", mp_count_bits(&a), tt);
      }
   }
   fclose(log);
   fclose(logb);
   fclose(logc);
   fclose(logd);

   log = fopen("logs/invmod.log", "w");
   for (cnt = 4; cnt <= 128; cnt += 4) {
      SLEEP;
      mp_rand(&a, cnt);
      mp_rand(&b, cnt);

      do {
	 mp_add_d(&b, 1, &b);
	 mp_gcd(&a, &b, &c);
      } while (mp_cmp_d(&c, 1) != MP_EQ);

      rr = 0;
      tt = -1;
      do {
	 gg = TIMFUNC();
	 DO(mp_invmod(&b, &a, &c));
	 gg = (TIMFUNC() - gg) >> 1;
	 if (tt > gg)
	    tt = gg;
      } while (++rr < 1000);
      mp_mulmod(&b, &c, &a, &d);
      if (mp_cmp_d(&d, 1) != MP_EQ) {
	 printf("Failed to invert\n");
	 return 0;
      }
      printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu cycles\n",
	     mp_count_bits(&a), CLK_PER_SEC / tt, tt);
      fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
   }
   fclose(log);

   return 0;
}

Added libtommath/dep.pl.























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
#!/usr/bin/perl 
#
# Walk through source, add labels and make classes
#
#use strict;

my %deplist;

#open class file and write preamble 
open(CLASS, ">tommath_class.h") or die "Couldn't open tommath_class.h for writing\n";
print CLASS "#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n#if defined(LTM2)\n#define LTM3\n#endif\n#if defined(LTM1)\n#define LTM2\n#endif\n#define LTM1\n\n#if defined(LTM_ALL)\n";

foreach my $filename (glob "bn*.c") {
   my $define = $filename;

print "Processing $filename\n";

   # convert filename to upper case so we can use it as a define 
   $define =~ tr/[a-z]/[A-Z]/;
   $define =~ tr/\./_/;
   print CLASS "#define $define\n";

   # now copy text and apply #ifdef as required 
   my $apply = 0;
   open(SRC, "<$filename");
   open(OUT, ">tmp");

   # first line will be the #ifdef
   my $line = <SRC>;
   if ($line =~ /include/) {
      print OUT $line;
   } else {
      print OUT "#include <tommath.h>\n#ifdef $define\n$line";
      $apply = 1;
   }
   while (<SRC>) {
      if (!($_ =~ /tommath\.h/)) {
         print OUT $_;
      }
   }
   if ($apply == 1) {
      print OUT "#endif\n";
   }
   close SRC;
   close OUT;

   unlink($filename);
   rename("tmp", $filename);
}
print CLASS "#endif\n\n";

# now do classes 

foreach my $filename (glob "bn*.c") {
   open(SRC, "<$filename") or die "Can't open source file!\n"; 

   # convert filename to upper case so we can use it as a define 
   $filename =~ tr/[a-z]/[A-Z]/;
   $filename =~ tr/\./_/;

   print CLASS "#if defined($filename)\n";
   my $list = $filename;

   # scan for mp_* and make classes
   while (<SRC>) {
      my $line = $_;
      while ($line =~ m/(fast_)*(s_)*mp\_[a-z_0-9]*/) {
          $line = $';
          # now $& is the match, we want to skip over LTM keywords like
          # mp_int, mp_word, mp_digit
          if (!($& eq "mp_digit") && !($& eq "mp_word") && !($& eq "mp_int")) {
             my $a = $&;
             $a =~ tr/[a-z]/[A-Z]/;
             $a = "BN_" . $a . "_C";
             if (!($list =~ /$a/)) {
                print CLASS "   #define $a\n";
             }
             $list = $list . "," . $a;
          }
      }
   }
   @deplist{$filename} = $list;

   print CLASS "#endif\n\n";
   close SRC;
}

print CLASS "#ifdef LTM3\n#define LTM_LAST\n#endif\n#include <tommath_superclass.h>\n#include <tommath_class.h>\n#else\n#define LTM_LAST\n#endif\n";
close CLASS;

#now let's make a cool call graph... 

open(OUT,">callgraph.txt");
$indent = 0;
foreach (keys %deplist) {
   $list = "";
   draw_func(@deplist{$_});
   print OUT "\n\n";
}
close(OUT);

sub draw_func()
{
   my @funcs = split(",", $_[0]);
   if ($list =~ /@funcs[0]/) {
      return;
   } else {
      $list = $list . @funcs[0];
   }
   if ($indent == 0) { }
   elsif ($indent >= 1) { print OUT "|   " x ($indent - 1) . "+--->"; }
   print OUT @funcs[0] . "\n";   
   shift @funcs;
      my $temp = $list;
   foreach my $i (@funcs) {
      ++$indent;
      draw_func(@deplist{$i});
      --$indent;
   }
      $list = $temp;
}


Added libtommath/etc/2kprime.1.





>
>
1
2
256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823
512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979

Added libtommath/etc/2kprime.c.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/* Makes safe primes of a 2k nature */
#include <tommath.h>
#include <time.h>

int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096};

int main(void)
{
   char buf[2000];
   int x, y;
   mp_int q, p;
   FILE *out;
   clock_t t1;
   mp_digit z;
   
   mp_init_multi(&q, &p, NULL);
   
   out = fopen("2kprime.1", "w");
   for (x = 0; x < (int)(sizeof(sizes) / sizeof(sizes[0])); x++) {
   top:
       mp_2expt(&q, sizes[x]);
       mp_add_d(&q, 3, &q);
       z = -3;
       
       t1 = clock();
       for(;;) {
         mp_sub_d(&q, 4, &q);
         z += 4;

         if (z > MP_MASK) {
            printf("No primes of size %d found\n", sizes[x]);
            break;
         }
         
         if (clock() - t1 > CLOCKS_PER_SEC) { 
            printf("."); fflush(stdout);
//            sleep((clock() - t1 + CLOCKS_PER_SEC/2)/CLOCKS_PER_SEC);
            t1 = clock();
         }
         
         /* quick test on q */
         mp_prime_is_prime(&q, 1, &y);
         if (y == 0) {
            continue;
         }

         /* find (q-1)/2 */
         mp_sub_d(&q, 1, &p);
         mp_div_2(&p, &p);
         mp_prime_is_prime(&p, 3, &y);
         if (y == 0) {
            continue;
         }

         /* test on q */
         mp_prime_is_prime(&q, 3, &y);
         if (y == 0) {
            continue;
         }

         break;
       }
       
       if (y == 0) {
          ++sizes[x];
          goto top;
       }
       
       mp_toradix(&q, buf, 10);
       printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf);
       fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fflush(out);
   }
   
   return 0;
}   

Added libtommath/etc/drprime.c.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/* Makes safe primes of a DR nature */
#include <tommath.h>

int sizes[] = { 1+256/DIGIT_BIT, 1+512/DIGIT_BIT, 1+768/DIGIT_BIT, 1+1024/DIGIT_BIT, 1+2048/DIGIT_BIT, 1+4096/DIGIT_BIT };
int main(void)
{
   int res, x, y;
   char buf[4096];
   FILE *out;
   mp_int a, b;
   
   mp_init(&a);
   mp_init(&b);
   
   out = fopen("drprimes.txt", "w");
   for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) {
   top:
       printf("Seeking a %d-bit safe prime\n", sizes[x] * DIGIT_BIT);
       mp_grow(&a, sizes[x]);
       mp_zero(&a);
       for (y = 1; y < sizes[x]; y++) {
           a.dp[y] = MP_MASK;
       }
       
       /* make a DR modulus */
       a.dp[0] = -1;
       a.used = sizes[x];
       
       /* now loop */
       res = 0;
       for (;;) { 
          a.dp[0] += 4;
          if (a.dp[0] >= MP_MASK) break;
          mp_prime_is_prime(&a, 1, &res);
          if (res == 0) continue;
          printf("."); fflush(stdout);
          mp_sub_d(&a, 1, &b);
          mp_div_2(&b, &b);
          mp_prime_is_prime(&b, 3, &res);  
          if (res == 0) continue;
          mp_prime_is_prime(&a, 3, &res);
          if (res == 1) break;
	}
        
        if (res != 1) {
           printf("Error not DR modulus\n"); sizes[x] += 1; goto top;
        } else {
           mp_toradix(&a, buf, 10);
           printf("\n\np == %s\n\n", buf);
           fprintf(out, "%d-bit prime:\np == %s\n\n", mp_count_bits(&a), buf); fflush(out);
        }           
   }
   fclose(out);
   
   mp_clear(&a);
   mp_clear(&b);
   
   return 0;
}

Added libtommath/etc/drprimes.28.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
DR safe primes for 28-bit digits.

224-bit prime:
p == 26959946667150639794667015087019630673637144422540572481103341844143

532-bit prime:
p == 14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368691747

784-bit prime:
p == 101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039

1036-bit prime:
p == 736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821798437127

1540-bit prime:
p == 38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783

2072-bit prime:
p == 542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147

3080-bit prime:
p == 1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503

4116-bit prime:
p == 1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679

Added libtommath/etc/drprimes.txt.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
300-bit prime:
p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819

540-bit prime:
p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739

780-bit prime:
p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167

Added libtommath/etc/makefile.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -I../

# default lib name (requires install with root)
# LIBNAME=-ltommath

# libname when you can't install the lib with install
LIBNAME=../libtommath.a

#provable primes
pprime: pprime.o
	$(CC) pprime.o $(LIBNAME) -o pprime

# portable [well requires clock()] tuning app
tune: tune.o
	$(CC) tune.o $(LIBNAME) -o tune
	
# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp]
tune86: tune.c
	nasm -f coff timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o  $(LIBNAME) -o tune86
	
# for cygwin
tune86c: tune.c
	nasm -f gnuwin32 timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o  $(LIBNAME) -o tune86

#make tune86 for linux or any ELF format
tune86l: tune.c
	nasm -f elf -DUSE_ELF timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l
        
# spits out mersenne primes
mersenne: mersenne.o
	$(CC) mersenne.o $(LIBNAME) -o mersenne

# fines DR safe primes for the given config
drprime: drprime.o
	$(CC) drprime.o $(LIBNAME) -o drprime
	
# fines 2k safe primes for the given config
2kprime: 2kprime.o
	$(CC) 2kprime.o $(LIBNAME) -o 2kprime

mont: mont.o
	$(CC) mont.o $(LIBNAME) -o mont

        
clean:
	rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat \
         *.da *.dyn *.dpi *~

Added libtommath/etc/makefile.icc.







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
CC = icc

CFLAGS += -I../

# optimize for SPEED
#
# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
# -ax?   specifies make code specifically for ? but compatible with IA-32
# -x?    specifies compile solely for ? [not specifically IA-32 compatible]
#
# where ? is 
#   K - PIII
#   W - first P4 [Williamette]
#   N - P4 Northwood
#   P - P4 Prescott
#   B - Blend of P4 and PM [mobile]
#
# Default to just generic max opts
CFLAGS += -O3 -xP -ip

# default lib name (requires install with root)
# LIBNAME=-ltommath

# libname when you can't install the lib with install
LIBNAME=../libtommath.a

#provable primes
pprime: pprime.o
	$(CC) pprime.o $(LIBNAME) -o pprime

# portable [well requires clock()] tuning app
tune: tune.o
	$(CC) tune.o $(LIBNAME) -o tune
	
# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp]
tune86: tune.c
	nasm -f coff timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o  $(LIBNAME) -o tune86
	
# for cygwin
tune86c: tune.c
	nasm -f gnuwin32 timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o  $(LIBNAME) -o tune86

#make tune86 for linux or any ELF format
tune86l: tune.c
	nasm -f elf -DUSE_ELF timer.asm
	$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l
        
# spits out mersenne primes
mersenne: mersenne.o
	$(CC) mersenne.o $(LIBNAME) -o mersenne

# fines DR safe primes for the given config
drprime: drprime.o
	$(CC) drprime.o $(LIBNAME) -o drprime
	
# fines 2k safe primes for the given config
2kprime: 2kprime.o
	$(CC) 2kprime.o $(LIBNAME) -o 2kprime

mont: mont.o
	$(CC) mont.o $(LIBNAME) -o mont

        
clean:
	rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat *.il

Added libtommath/etc/makefile.msvc.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#MSVC Makefile
#
#Tom St Denis

CFLAGS = /I../ /Ox /DWIN32 /W3

pprime: pprime.obj
	cl pprime.obj ../tommath.lib 

mersenne: mersenne.obj
	cl mersenne.obj ../tommath.lib
	
tune: tune.obj
	cl tune.obj ../tommath.lib

mont: mont.obj
	cl mont.obj ../tommath.lib
	
drprime: drprime.obj
	cl drprime.obj ../tommath.lib

2kprime: 2kprime.obj
	cl 2kprime.obj ../tommath.lib

Added libtommath/etc/mersenne.c.

























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* Finds Mersenne primes using the Lucas-Lehmer test 
 *
 * Tom St Denis, [email protected]
 */
#include <time.h>
#include <tommath.h>

int
is_mersenne (long s, int *pp)
{
  mp_int  n, u;
  int     res, k;
  
  *pp = 0;

  if ((res = mp_init (&n)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&u)) != MP_OKAY) {
    goto LBL_N;
  }

  /* n = 2^s - 1 */
  if ((res = mp_2expt(&n, s)) != MP_OKAY) {
     goto LBL_MU;
  }
  if ((res = mp_sub_d (&n, 1, &n)) != MP_OKAY) {
    goto LBL_MU;
  }

  /* set u=4 */
  mp_set (&u, 4);

  /* for k=1 to s-2 do */
  for (k = 1; k <= s - 2; k++) {
    /* u = u^2 - 2 mod n */
    if ((res = mp_sqr (&u, &u)) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) {
      goto LBL_MU;
    }

    /* make sure u is positive */
    while (u.sign == MP_NEG) {
      if ((res = mp_add (&u, &n, &u)) != MP_OKAY) {
         goto LBL_MU;
      }
    }

    /* reduce */
    if ((res = mp_reduce_2k (&u, &n, 1)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* if u == 0 then its prime */
  if (mp_iszero (&u) == 1) {
    mp_prime_is_prime(&n, 8, pp);
  if (*pp != 1) printf("FAILURE\n");
  }

  res = MP_OKAY;
LBL_MU:mp_clear (&u);
LBL_N:mp_clear (&n);
  return res;
}

/* square root of a long < 65536 */
long
i_sqrt (long x)
{
  long    x1, x2;

  x2 = 16;
  do {
    x1 = x2;
    x2 = x1 - ((x1 * x1) - x) / (2 * x1);
  } while (x1 != x2);

  if (x1 * x1 > x) {
    --x1;
  }

  return x1;
}

/* is the long prime by brute force */
int
isprime (long k)
{
  long    y, z;

  y = i_sqrt (k);
  for (z = 2; z <= y; z++) {
    if ((k % z) == 0)
      return 0;
  }
  return 1;
}


int
main (void)
{
  int     pp;
  long    k;
  clock_t tt;

  k = 3;

  for (;;) {
    /* start time */
    tt = clock ();

    /* test if 2^k - 1 is prime */
    if (is_mersenne (k, &pp) != MP_OKAY) {
      printf ("Whoa error\n");
      return -1;
    }

    if (pp == 1) {
      /* count time */
      tt = clock () - tt;

      /* display if prime */
      printf ("2^%-5ld - 1 is prime, test took %ld ticks\n", k, tt);
    }

    /* goto next odd exponent */
    k += 2;

    /* but make sure its prime */
    while (isprime (k) == 0) {
      k += 2;
    }
  }
  return 0;
}

Added libtommath/etc/mont.c.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/* tests the montgomery routines */
#include <tommath.h>

int main(void)
{
   mp_int modulus, R, p, pp;
   mp_digit mp;
   long x, y;

   srand(time(NULL));
   mp_init_multi(&modulus, &R, &p, &pp, NULL);

   /* loop through various sizes */
   for (x = 4; x < 256; x++) {
       printf("DIGITS == %3ld...", x); fflush(stdout);
       
       /* make up the odd modulus */
       mp_rand(&modulus, x);
       modulus.dp[0] |= 1;
       
       /* now find the R value */
       mp_montgomery_calc_normalization(&R, &modulus);
       mp_montgomery_setup(&modulus, &mp);
       
       /* now run through a bunch tests */
       for (y = 0; y < 1000; y++) {
           mp_rand(&p, x/2);        /* p = random */
           mp_mul(&p, &R, &pp);     /* pp = R * p */
           mp_montgomery_reduce(&pp, &modulus, mp);
           
           /* should be equal to p */
           if (mp_cmp(&pp, &p) != MP_EQ) {
              printf("FAILURE!\n");
              exit(-1);
           }
       }
       printf("PASSED\n");
    }
    
    return 0;
}

Added libtommath/etc/pprime.c.

























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/* Generates provable primes
 *
 * See http://gmail.com:8080/papers/pp.pdf for more info.
 *
 * Tom St Denis, [email protected], http://tom.gmail.com
 */
#include <time.h>
#include "tommath.h"

int   n_prime;
FILE *primes;

/* fast square root */
static  mp_digit
i_sqrt (mp_word x)
{
  mp_word x1, x2;

  x2 = x;
  do {
    x1 = x2;
    x2 = x1 - ((x1 * x1) - x) / (2 * x1);
  } while (x1 != x2);

  if (x1 * x1 > x) {
    --x1;
  }

  return x1;
}


/* generates a prime digit */
static void gen_prime (void)
{
  mp_digit r, x, y, next;
  FILE *out;

  out = fopen("pprime.dat", "wb");

  /* write first set of primes */
  r = 3; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 5; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 7; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 11; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 13; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 17; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 19; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 23; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 29; fwrite(&r, 1, sizeof(mp_digit), out);
  r = 31; fwrite(&r, 1, sizeof(mp_digit), out);

  /* get square root, since if 'r' is composite its factors must be < than this */
  y = i_sqrt (r);
  next = (y + 1) * (y + 1);

  for (;;) {
  do {
    r += 2;			/* next candidate */
    r &= MP_MASK;
    if (r < 31) break;

    /* update sqrt ? */
    if (next <= r) {
      ++y;
      next = (y + 1) * (y + 1);
    }

    /* loop if divisible by 3,5,7,11,13,17,19,23,29  */
    if ((r % 3) == 0) {
      x = 0;
      continue;
    }
    if ((r % 5) == 0) {
      x = 0;
      continue;
    }
    if ((r % 7) == 0) {
      x = 0;
      continue;
    }
    if ((r % 11) == 0) {
      x = 0;
      continue;
    }
    if ((r % 13) == 0) {
      x = 0;
      continue;
    }
    if ((r % 17) == 0) {
      x = 0;
      continue;
    }
    if ((r % 19) == 0) {
      x = 0;
      continue;
    }
    if ((r % 23) == 0) {
      x = 0;
      continue;
    }
    if ((r % 29) == 0) {
      x = 0;
      continue;
    }

    /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */
    for (x = 30; x <= y; x += 30) {
      if ((r % (x + 1)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 7)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 11)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 13)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 17)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 19)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 23)) == 0) {
	x = 0;
	break;
      }
      if ((r % (x + 29)) == 0) {
	x = 0;
	break;
      }
    }
  } while (x == 0);
  if (r > 31) { fwrite(&r, 1, sizeof(mp_digit), out); printf("%9d\r", r); fflush(stdout); }
  if (r < 31) break;
  }

  fclose(out);
}

void load_tab(void)
{
   primes = fopen("pprime.dat", "rb");
   if (primes == NULL) {
      gen_prime();
      primes = fopen("pprime.dat", "rb");
   }
   fseek(primes, 0, SEEK_END);
   n_prime = ftell(primes) / sizeof(mp_digit);
}

mp_digit prime_digit(void)
{
   int n;
   mp_digit d;

   n = abs(rand()) % n_prime;
   fseek(primes, n * sizeof(mp_digit), SEEK_SET);
   fread(&d, 1, sizeof(mp_digit), primes);
   return d;
}


/* makes a prime of at least k bits */
int
pprime (int k, int li, mp_int * p, mp_int * q)
{
  mp_int  a, b, c, n, x, y, z, v;
  int     res, ii;
  static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 };

  /* single digit ? */
  if (k <= (int) DIGIT_BIT) {
    mp_set (p, prime_digit ());
    return MP_OKAY;
  }

  if ((res = mp_init (&c)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&v)) != MP_OKAY) {
    goto LBL_C;
  }

  /* product of first 50 primes */
  if ((res =
       mp_read_radix (&v,
		      "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190",
		      10)) != MP_OKAY) {
    goto LBL_V;
  }

  if ((res = mp_init (&a)) != MP_OKAY) {
    goto LBL_V;
  }

  /* set the prime */
  mp_set (&a, prime_digit ());

  if ((res = mp_init (&b)) != MP_OKAY) {
    goto LBL_A;
  }

  if ((res = mp_init (&n)) != MP_OKAY) {
    goto LBL_B;
  }

  if ((res = mp_init (&x)) != MP_OKAY) {
    goto LBL_N;
  }

  if ((res = mp_init (&y)) != MP_OKAY) {
    goto LBL_X;
  }

  if ((res = mp_init (&z)) != MP_OKAY) {
    goto LBL_Y;
  }

  /* now loop making the single digit */
  while (mp_count_bits (&a) < k) {
    fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a));
    fflush (stderr);
  top:
    mp_set (&b, prime_digit ());

    /* now compute z = a * b * 2 */
    if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) {	/* z = a * b */
      goto LBL_Z;
    }

    if ((res = mp_copy (&z, &c)) != MP_OKAY) {	/* c = a * b */
      goto LBL_Z;
    }

    if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) {	/* z = 2 * a * b */
      goto LBL_Z;
    }

    /* n = z + 1 */
    if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) {	/* n = z + 1 */
      goto LBL_Z;
    }

    /* check (n, v) == 1 */
    if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) {	/* y = (n, v) */
      goto LBL_Z;
    }

    if (mp_cmp_d (&y, 1) != MP_EQ)
      goto top;

    /* now try base x=bases[ii]  */
    for (ii = 0; ii < li; ii++) {
      mp_set (&x, bases[ii]);

      /* compute x^a mod n */
      if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) {	/* y = x^a mod n */
	goto LBL_Z;
      }

      /* if y == 1 loop */
      if (mp_cmp_d (&y, 1) == MP_EQ)
	continue;

      /* now x^2a mod n */
      if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) {	/* y = x^2a mod n */
	goto LBL_Z;
      }

      if (mp_cmp_d (&y, 1) == MP_EQ)
	continue;

      /* compute x^b mod n */
      if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) {	/* y = x^b mod n */
	goto LBL_Z;
      }

      /* if y == 1 loop */
      if (mp_cmp_d (&y, 1) == MP_EQ)
	continue;

      /* now x^2b mod n */
      if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) {	/* y = x^2b mod n */
	goto LBL_Z;
      }

      if (mp_cmp_d (&y, 1) == MP_EQ)
	continue;

      /* compute x^c mod n == x^ab mod n */
      if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) {	/* y = x^ab mod n */
	goto LBL_Z;
      }

      /* if y == 1 loop */
      if (mp_cmp_d (&y, 1) == MP_EQ)
	continue;

      /* now compute (x^c mod n)^2 */
      if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) {	/* y = x^2ab mod n */
	goto LBL_Z;
      }

      /* y should be 1 */
      if (mp_cmp_d (&y, 1) != MP_EQ)
	continue;
      break;
    }

    /* no bases worked? */
    if (ii == li)
      goto top;

{
   char buf[4096];

   mp_toradix(&n, buf, 10);
   printf("Certificate of primality for:\n%s\n\n", buf);
   mp_toradix(&a, buf, 10);
   printf("A == \n%s\n\n", buf);
   mp_toradix(&b, buf, 10);
   printf("B == \n%s\n\nG == %d\n", buf, bases[ii]);
   printf("----------------------------------------------------------------\n");
}

    /* a = n */
    mp_copy (&n, &a);
  }

  /* get q to be the order of the large prime subgroup */
  mp_sub_d (&n, 1, q);
  mp_div_2 (q, q);
  mp_div (q, &b, q, NULL);

  mp_exch (&n, p);

  res = MP_OKAY;
LBL_Z:mp_clear (&z);
LBL_Y:mp_clear (&y);
LBL_X:mp_clear (&x);
LBL_N:mp_clear (&n);
LBL_B:mp_clear (&b);
LBL_A:mp_clear (&a);
LBL_V:mp_clear (&v);
LBL_C:mp_clear (&c);
  return res;
}


int
main (void)
{
  mp_int  p, q;
  char    buf[4096];
  int     k, li;
  clock_t t1;

  srand (time (NULL));
  load_tab();

  printf ("Enter # of bits: \n");
  fgets (buf, sizeof (buf), stdin);
  sscanf (buf, "%d", &k);

  printf ("Enter number of bases to try (1 to 8):\n");
  fgets (buf, sizeof (buf), stdin);
  sscanf (buf, "%d", &li);


  mp_init (&p);
  mp_init (&q);

  t1 = clock ();
  pprime (k, li, &p, &q);
  t1 = clock () - t1;

  printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p));

  mp_toradix (&p, buf, 10);
  printf ("P == %s\n", buf);
  mp_toradix (&q, buf, 10);
  printf ("Q == %s\n", buf);

  return 0;
}

Added libtommath/etc/prime.1024.





























































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
Enter # of bits: 
Enter number of bases to try (1 to 8):
Certificate of primality for:
36360080703173363

A == 
89963569

B == 
202082249

G == 2
----------------------------------------------------------------
Certificate of primality for:
4851595597739856136987139

A == 
36360080703173363

B == 
66715963

G == 2
----------------------------------------------------------------
Certificate of primality for:
19550639734462621430325731591027

A == 
4851595597739856136987139

B == 
2014867

G == 2
----------------------------------------------------------------
Certificate of primality for:
10409036141344317165691858509923818734539

A == 
19550639734462621430325731591027

B == 
266207047

G == 2
----------------------------------------------------------------
Certificate of primality for:
1049829549988285012736475602118094726647504414203

A == 
10409036141344317165691858509923818734539

B == 
50428759

G == 2
----------------------------------------------------------------
Certificate of primality for:
77194737385528288387712399596835459931920358844586615003

A == 
1049829549988285012736475602118094726647504414203

B == 
36765367

G == 2
----------------------------------------------------------------
Certificate of primality for:
35663756695365208574443215955488689578374232732893628896541201763

A == 
77194737385528288387712399596835459931920358844586615003

B == 
230998627

G == 2
----------------------------------------------------------------
Certificate of primality for:
16711831463502165169495622246023119698415848120292671294127567620396469803

A == 
35663756695365208574443215955488689578374232732893628896541201763

B == 
234297127

G == 2
----------------------------------------------------------------
Certificate of primality for:
6163534781560285962890718925972249753147470953579266394395432475622345597103528739

A == 
16711831463502165169495622246023119698415848120292671294127567620396469803

B == 
184406323

G == 2
----------------------------------------------------------------
Certificate of primality for:
814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787

A == 
6163534781560285962890718925972249753147470953579266394395432475622345597103528739

B == 
66054487

G == 2
----------------------------------------------------------------
Certificate of primality for:
176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187

A == 
814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787

B == 
108362239

G == 2
----------------------------------------------------------------
Certificate of primality for:
44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419

A == 
176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187

B == 
127286707

G == 2
----------------------------------------------------------------
Certificate of primality for:
20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059

A == 
44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419

B == 
229284691

G == 2
----------------------------------------------------------------
Certificate of primality for:
6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979

A == 
20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059

B == 
152800771

G == 2
----------------------------------------------------------------
Certificate of primality for:
3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123

A == 
6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979

B == 
246595759

G == 2
----------------------------------------------------------------
Certificate of primality for:
26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499

A == 
3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123

B == 
4252063

G == 2
----------------------------------------------------------------
Certificate of primality for:
11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163

A == 
26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499

B == 
210605419

G == 2
----------------------------------------------------------------
Certificate of primality for:
1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187

A == 
11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163

B == 
74170111

G == 2
----------------------------------------------------------------
Certificate of primality for:
857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363

A == 
1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187

B == 
260016763

G == 2
----------------------------------------------------------------
Certificate of primality for:
175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283

A == 
857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363

B == 
102563707

G == 2
----------------------------------------------------------------
Certificate of primality for:
48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283

A == 
175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283

B == 
137747527

G == 2
----------------------------------------------------------------
Certificate of primality for:
13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403

A == 
48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283

B == 
135672847

G == 2
----------------------------------------------------------------
Certificate of primality for:
6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123

A == 
13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403

B == 
241523587

G == 2
----------------------------------------------------------------
Certificate of primality for:
3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083

A == 
6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123

B == 
248388667

G == 2
----------------------------------------------------------------
Certificate of primality for:
390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067

A == 
3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083

B == 
61849651

G == 2
----------------------------------------------------------------
Certificate of primality for:
48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739

A == 
390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067

B == 
62201707

G == 2
----------------------------------------------------------------
Certificate of primality for:
25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419

A == 
48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739

B == 
264832231

G == 2
----------------------------------------------------------------
Certificate of primality for:
2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387

A == 
25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419

B == 
54494047

G == 2
----------------------------------------------------------------
Certificate of primality for:
738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547

A == 
2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387

B == 
131594179

G == 2
----------------------------------------------------------------
Certificate of primality for:
392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683

A == 
738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547

B == 
266107603

G == 2
----------------------------------------------------------------
Certificate of primality for:
168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627

A == 
392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683

B == 
214408111

G == 2
----------------------------------------------------------------
Certificate of primality for:
14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643

A == 
168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627

B == 
44122723

G == 2
----------------------------------------------------------------
Certificate of primality for:
1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019

A == 
14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643

B == 
40808563

G == 2
----------------------------------------------------------------
Certificate of primality for:
186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843

A == 
1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019

B == 
77035759

G == 2
----------------------------------------------------------------
Certificate of primality for:
83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683

A == 
186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843

B == 
222383587

G == 2
----------------------------------------------------------------
Certificate of primality for:
3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443

A == 
83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683

B == 
23407687

G == 2
----------------------------------------------------------------
Certificate of primality for:
1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723

A == 
3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443

B == 
213701827

G == 2
----------------------------------------------------------------


Took 33057 ticks, 1048 bits
P == 1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723
Q == 3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443

Added libtommath/etc/prime.512.



























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
Enter # of bits: 
Enter number of bases to try (1 to 8):
Certificate of primality for:
85933926807634727

A == 
253758023

B == 
169322581

G == 5
----------------------------------------------------------------
Certificate of primality for:
23930198825086241462113799

A == 
85933926807634727

B == 
139236037

G == 11
----------------------------------------------------------------
Certificate of primality for:
6401844647261612602378676572510019

A == 
23930198825086241462113799

B == 
133760791

G == 2
----------------------------------------------------------------
Certificate of primality for:
269731366027728777712034888684015329354259

A == 
6401844647261612602378676572510019

B == 
21066691

G == 2
----------------------------------------------------------------
Certificate of primality for:
37942338209025571690075025099189467992329684223707

A == 
269731366027728777712034888684015329354259

B == 
70333567

G == 2
----------------------------------------------------------------
Certificate of primality for:
15306904714258982484473490774101705363308327436988160248323

A == 
37942338209025571690075025099189467992329684223707

B == 
201712723

G == 2
----------------------------------------------------------------
Certificate of primality for:
1616744757018513392810355191503853040357155275733333124624513530099

A == 
15306904714258982484473490774101705363308327436988160248323

B == 
52810963

G == 2
----------------------------------------------------------------
Certificate of primality for:
464222094814208047161771036072622485188658077940154689939306386289983787983

A == 
1616744757018513392810355191503853040357155275733333124624513530099

B == 
143566909

G == 5
----------------------------------------------------------------
Certificate of primality for:
187429931674053784626487560729643601208757374994177258429930699354770049369025096447

A == 
464222094814208047161771036072622485188658077940154689939306386289983787983

B == 
201875281

G == 5
----------------------------------------------------------------
Certificate of primality for:
100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563

A == 
187429931674053784626487560729643601208757374994177258429930699354770049369025096447

B == 
268311523

G == 2
----------------------------------------------------------------
Certificate of primality for:
1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163

A == 
100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563

B == 
5834287

G == 2
----------------------------------------------------------------
Certificate of primality for:
191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623

A == 
1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163

B == 
81567097

G == 5
----------------------------------------------------------------
Certificate of primality for:
57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519

A == 
191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623

B == 
151095433

G == 7
----------------------------------------------------------------
Certificate of primality for:
13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803

A == 
57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519

B == 
119178679

G == 2
----------------------------------------------------------------
Certificate of primality for:
7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979

A == 
13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803

B == 
256552363

G == 2
----------------------------------------------------------------
Certificate of primality for:
1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463

A == 
7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979

B == 
86720989

G == 5
----------------------------------------------------------------
Certificate of primality for:
446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763

A == 
1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463

B == 
182015287

G == 2
----------------------------------------------------------------
Certificate of primality for:
5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243

A == 
446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763

B == 
5920567

G == 2
----------------------------------------------------------------


Took 3454 ticks, 521 bits
P == 5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243
Q == 446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763

Added libtommath/etc/timer.asm.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
; x86 timer in NASM
;
; Tom St Denis, [email protected]
[bits 32]
[section .data]
time dd 0, 0

[section .text]

%ifdef USE_ELF
[global t_start]
t_start:
%else
[global _t_start]
_t_start:
%endif
   push edx
   push eax
   rdtsc
   mov [time+0],edx
   mov [time+4],eax
   pop eax
   pop edx
   ret
   
%ifdef USE_ELF
[global t_read]
t_read:
%else
[global _t_read]
_t_read:
%endif
   rdtsc
   sub eax,[time+4]
   sbb edx,[time+0]
   ret
   

Added libtommath/etc/tune.c.





















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Tune the Karatsuba parameters
 *
 * Tom St Denis, [email protected]
 */
#include <tommath.h>
#include <time.h>

/* how many times todo each size mult.  Depends on your computer.  For slow computers
 * this can be low like 5 or 10.  For fast [re: Athlon] should be 25 - 50 or so 
 */
#define TIMES (1UL<<14UL)

/* RDTSC from Scott Duplichan */
static ulong64 TIMFUNC (void)
   {
   #if defined __GNUC__
      #if defined(__i386__) || defined(__x86_64__)
         unsigned long long a;
         __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
         return a;
      #else /* gcc-IA64 version */
         unsigned long result;
         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
         while (__builtin_expect ((int) result == -1, 0))
         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
         return result;
      #endif

   // Microsoft and Intel Windows compilers
   #elif defined _M_IX86
     __asm rdtsc
   #elif defined _M_AMD64
     return __rdtsc ();
   #elif defined _M_IA64
     #if defined __INTEL_COMPILER
       #include <ia64intrin.h>
     #endif
      return __getReg (3116);
   #else
     #error need rdtsc function for this build
   #endif
   }


#ifndef X86_TIMER

/* generic ISO C timer */
ulong64 LBL_T;
void t_start(void) { LBL_T = TIMFUNC(); }
ulong64 t_read(void) { return TIMFUNC() - LBL_T; }

#else
extern void t_start(void);
extern ulong64 t_read(void);
#endif

ulong64 time_mult(int size, int s)
{
  unsigned long     x;
  mp_int  a, b, c;
  ulong64 t1;

  mp_init (&a);
  mp_init (&b);
  mp_init (&c);

  mp_rand (&a, size);
  mp_rand (&b, size);

  if (s == 1) { 
      KARATSUBA_MUL_CUTOFF = size;
  } else {
      KARATSUBA_MUL_CUTOFF = 100000;
  }

  t_start();
  for (x = 0; x < TIMES; x++) {
      mp_mul(&a,&b,&c);
  }
  t1 = t_read();
  mp_clear (&a);
  mp_clear (&b);
  mp_clear (&c);
  return t1;
}

ulong64 time_sqr(int size, int s)
{
  unsigned long     x;
  mp_int  a, b;
  ulong64 t1;

  mp_init (&a);
  mp_init (&b);

  mp_rand (&a, size);

  if (s == 1) { 
      KARATSUBA_SQR_CUTOFF = size;
  } else {
      KARATSUBA_SQR_CUTOFF = 100000;
  }

  t_start();
  for (x = 0; x < TIMES; x++) {
      mp_sqr(&a,&b);
  }
  t1 = t_read();
  mp_clear (&a);
  mp_clear (&b);
  return t1;
}

int
main (void)
{
  ulong64 t1, t2;
  int x, y;

  for (x = 8; ; x += 2) { 
     t1 = time_mult(x, 0);
     t2 = time_mult(x, 1);
     printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
     if (t2 < t1) break;
  }
  y = x;

  for (x = 8; ; x += 2) { 
     t1 = time_sqr(x, 0);
     t2 = time_sqr(x, 1);
     printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
     if (t2 < t1) break;
  }
  printf("KARATSUBA_MUL_CUTOFF = %d\n", y);
  printf("KARATSUBA_SQR_CUTOFF = %d\n", x);

  return 0;
}

Added libtommath/gen.pl.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl -w
#
# Generates a "single file" you can use to quickly
# add the whole source without any makefile troubles
#
use strict;

open( OUT, ">mpi.c" ) or die "Couldn't open mpi.c for writing: $!";
foreach my $filename (glob "bn*.c") {
   open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
   print OUT "/* Start: $filename */\n";
   print OUT while <SRC>;
   print OUT "\n/* End: $filename */\n\n";
   close SRC or die "Error closing $filename after reading: $!";
}
print OUT "\n/* EOF */\n";
close OUT or die "Error closing mpi.c after writing: $!";

Added libtommath/logs/README.



























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package.  
Todo this type 

make timing ; ltmtest

in the root.  It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/.

After doing that run "gnuplot graphs.dem" to make the PNGs.  If you managed todo that all so far just open index.html to view
them all :-)

Have fun

Tom

Added libtommath/logs/add.log.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
480        87
960       111
1440       135
1920       159
2400       200
2880       224
3360       248
3840       272
4320       296
4800       320
5280       344
5760       368
6240       392
6720       416
7200       440
7680       464

Added libtommath/logs/addsub.png.

cannot compute difference between binary files

Added libtommath/logs/expt.log.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
513   1435869
769   3544970
1025   7791638
2049  46902238
2561  85334899
3073 141451412
4097 308770310

Added libtommath/logs/expt.png.

cannot compute difference between binary files

Added libtommath/logs/expt_2k.log.











>
>
>
>
>
1
2
3
4
5
607   2109225
1279  10148314
2203  34126877
3217  82716424
4253 161569606

Added libtommath/logs/expt_2kl.log.









>
>
>
>
1
2
3
4
1024   7705271
2048  34286851
4096 165207491
521   1618631

Added libtommath/logs/expt_dr.log.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
532   1928550
784   3763908
1036   7564221
1540  16566059
2072  32283784
3080  79851565
4116 157843530

Added libtommath/logs/graphs.dem.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
set terminal png
set size 1.75
set ylabel "Cycles per Operation"
set xlabel "Operand size (bits)"

set output "addsub.png"
plot 'add.log' smooth bezier title "Addition", 'sub.log' smooth bezier title "Subtraction"

set output "mult.png"
plot 'sqr.log' smooth bezier title "Squaring (without Karatsuba)", 'sqr_kara.log' smooth bezier title "Squaring (Karatsuba)", 'mult.log' smooth bezier title "Multiplication (without Karatsuba)", 'mult_kara.log' smooth bezier title "Multiplication (Karatsuba)"

set output "expt.png"
plot 'expt.log' smooth bezier title "Exptmod (Montgomery)", 'expt_dr.log' smooth bezier title "Exptmod (Dimminished Radix)", 'expt_2k.log' smooth bezier title "Exptmod (2k Reduction)"

set output "invmod.png"
plot 'invmod.log' smooth bezier title "Modular Inverse"

Added libtommath/logs/index.html.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
<title>LibTomMath Log Plots</title>
</head>
<body>

<h1>Addition and Subtraction</h1>
<center><img src=addsub.png></center>
<hr>

<h1>Multipliers</h1>
<center><img src=mult.png></center>
<hr>

<h1>Exptmod</h1>
<center><img src=expt.png></center>
<hr>

<h1>Modular Inverse</h1>
<center><img src=invmod.png></center>
<hr>

</body>
</html>

Added libtommath/logs/invmod.log.

Added libtommath/logs/invmod.png.

cannot compute difference between binary files

Added libtommath/logs/mult.log.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
271       555
390       855
508      1161
631      1605
749      2117
871      2687
991      3329
1108      4084
1231      4786
1351      5624
1470      6392
1586      7364
1710      8218
1830      9255
1951     10217
2067     11461
2191     12463
2308     13677
2430     14800
2551     16232
2671     17460
2791     18899
2902     20247
3028     21902
3151     23240
3267     24927
3391     26441
3511     28277
3631     29838
3749     31751
3869     33673
3989     35431
4111     37518
4231     39426
4349     41504
4471     43567
4591     45786
4711     47876
4831     50299
4951     52427
5071     54785
5189     57241
5307     59730
5431     62194
5551     64761
5670     67322
5789     70073
5907     72663
6030     75437
6151     78242
6268     81202
6389     83948
6509     86985
6631     89903
6747     93184
6869     96044
6991     99286
7109    102395
7229    105917
7351    108940
7470    112490
7589    115702
7711    119508
7831    122632
7951    126410
8071    129808
8190    133895
8311    137146
8431    141218
8549    144732
8667    149131
8790    152462
8911    156754
9030    160479
9149    165138
9271    168601
9391    173185
9511    176988
9627    181976
9751    185539
9870    190388
9991    194335
10110    199605
10228    203298

Added libtommath/logs/mult.png.

cannot compute difference between binary files

Added libtommath/logs/mult_kara.log.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
271       560
391       870
511      1159
631      1605
750      2111
871      2737
991      3361
1111      4054
1231      4778
1351      5600
1471      6404
1591      7323
1710      8255
1831      9239
1948     10257
2070     11397
2190     12531
2308     13665
2429     14870
2550     16175
2671     17539
2787     18879
2911     20350
3031     21807
3150     23415
3270     24897
3388     26567
3511     28205
3627     30076
3751     31744
3869     33657
3991     35425
4111     37522
4229     39363
4351     41503
4470     43491
4590     45827
4711     47795
4828     50166
4951     52318
5070     54911
5191     57036
5308     58237
5431     60248
5551     62678
5671     64786
5791     67294
5908     69343
6031     71607
6151     74166
6271     76590
6391     78734
6511     81175
6631     83742
6750     86403
6868     88873
6990     91150
7110     94211
7228     96922
7351     99445
7469    102216
7589    104968
7711    108113
7827    110758
7950    113714
8071    116511
8186    119643
8310    122679
8425    125581
8551    128715
8669    131778
8788    135116
8910    138138
9031    141628
9148    144754
9268    148367
9391    151551
9511    155033
9631    158652
9751    162125
9871    165248
9988    168627
10111    172427
10231    176412

Added libtommath/logs/sqr.log.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
265       562
389       882
509      1207
631      1572
750      1990
859      2433
991      2894
1109      3555
1230      4228
1350      5018
1471      5805
1591      6579
1709      7415
1829      8329
1949      9225
2071     10139
2188     11239
2309     12178
2431     13212
2551     14294
2671     15551
2791     16512
2911     17718
3030     18876
3150     20259
3270     21374
3391     22650
3511     23948
3631     25493
3750     26756
3870     28225
3989     29705
4110     31409
4230     32834
4351     34327
4471     35818
4591     37636
4711     39228
4830     40868
4949     42393
5070     44541
5191     46269
5310     48162
5429     49728
5548     51985
5671     53948
5791     55885
5910     57584
6031     60082
6150     62239
6270     64309
6390     66014
6511     68766
6631     71012
6750     73172
6871     74952
6991     77909
7111     80371
7231     82666
7351     84531
7469     87698
7589     90318
7711    225384
7830    232428
7950    240009
8070    246522
8190    253662
8310    260961
8431    269253
8549    275743
8671    283769
8789    290811
8911    300034
9030    306873
9149    315085
9270    323944
9390    332390
9508    337519
9631    348986
9749    356904
9871    367013
9989    373831
10108    381033
10230    393475

Added libtommath/logs/sqr_kara.log.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
271       560
388       878
511      1179
629      1625
751      1988
871      2423
989      2896
1111      3561
1231      4209
1350      5015
1470      5804
1591      6556
1709      7420
1831      8263
1951      9173
2070     10153
2191     11229
2310     12167
2431     13211
2550     14309
2671     15524
2788     16525
2910     17712
3028     18822
3148     20220
3271     21343
3391     22652
3511     23944
3630     25485
3750     26778
3868     28201
3990     29653
4111     31393
4225     32841
4350     34328
4471     35786
4590     37652
4711     39245
4830     40876
4951     42433
5068     44547
5191     46321
5311     48140
5430     49727
5550     52034
5671     53954
5791     55921
5908     57597
6031     60084
6148     62226
6270     64295
6390     66045
6511     68779
6629     71003
6751     73169
6871     74992
6991     77895
7110     80376
7231     82628
7351     84468
7470     87664
7591     90284
7711     91352
7828     93995
7950     96276
8071     98691
8190    101256
8308    103631
8431    105222
8550    108343
8671    110281
8787    112764
8911    115397
9031    117690
9151    120266
9271    122715
9391    124624
9510    127937
9630    130313
9750    132914
9871    136129
9991    138517
10108    141525
10231    144225

Added libtommath/logs/sub.log.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
480        94
960       116
1440       140
1920       164
2400       205
2880       229
3360       253
3840       277
4320       299
4800       321
5280       345
5760       371
6240       395
6720       419
7200       441
7680       465

Added libtommath/makefile.bcc.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#
# Borland C++Builder Makefile (makefile.bcc)
#


LIB = tlib
CC = bcc32
CFLAGS = -c -O2 -I.

OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \
bn_mp_clamp.obj bn_mp_zero.obj  bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \
bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \
bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \
bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \
bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \
bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \
bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \
bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \
bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \
bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \
bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \
bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj  \
bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \
bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \
bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \
bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \
bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
bn_mp_reduce_2k_l.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_2k_setup_l.obj \
bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \
bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \
bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj \
bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj

TARGET = libtommath.lib

$(TARGET): $(OBJECTS)

.c.obj:
	$(CC) $(CFLAGS) $<
	$(LIB) $(TARGET) -+$@

Added libtommath/makefile.cygwin_dll.







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#Makefile for Cygwin-GCC
#
#This makefile will build a Windows DLL [doesn't require cygwin to run] in the file
#libtommath.dll.  The import library is in libtommath.dll.a.  Remember to add
#"-Wl,--enable-auto-import" to your client build to avoid the auto-import warnings
#
#Tom St Denis
CFLAGS  +=  -I./ -Wall -W -Wshadow -O3 -funroll-loops -mno-cygwin

#x86 optimizations [should be valid for any GCC install though]
CFLAGS  += -fomit-frame-pointer 

default: windll

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o

# make a Windows DLL via Cygwin
windll:  $(OBJECTS)
	gcc -mno-cygwin -mdll -o libtommath.dll -Wl,--out-implib=libtommath.dll.a -Wl,--export-all-symbols *.o
	ranlib libtommath.dll.a

# build the test program using the windows DLL
test: $(OBJECTS) windll
	gcc $(CFLAGS) demo/demo.c libtommath.dll.a -Wl,--enable-auto-import -o test -s
	cd mtest ; $(CC) -O3 -fomit-frame-pointer -funroll-loops mtest.c -o mtest -s

Added libtommath/makefile.icc.









































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#Makefile for ICC
#
#Tom St Denis
CC=icc

CFLAGS  +=  -I./

# optimize for SPEED
#
# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
# -ax?   specifies make code specifically for ? but compatible with IA-32
# -x?    specifies compile solely for ? [not specifically IA-32 compatible]
#
# where ? is 
#   K - PIII
#   W - first P4 [Williamette]
#   N - P4 Northwood
#   P - P4 Prescott
#   B - Blend of P4 and PM [mobile]
#
# Default to just generic max opts
CFLAGS += -O3 -xP -ip

#install as this user
USER=root
GROUP=root

default: libtommath.a

#default files to install
LIBNAME=libtommath.a
HEADERS=tommath.h

#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtommath.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtommath/pdf

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o

libtommath.a:  $(OBJECTS)
	$(AR) $(ARFLAGS) libtommath.a $(OBJECTS)
	ranlib libtommath.a

#make a profiled library (takes a while!!!)
#
# This will build the library with profile generation
# then run the test demo and rebuild the library.
# 
# So far I've seen improvements in the MP math
profiled:
	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen -DTESTING" timing
	./ltmtest
	rm -f *.a *.o ltmtest
	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use"

#make a single object profiled library 
profiled_single:
	perl gen.pl
	$(CC) $(CFLAGS) -prof_gen -DTESTING -c mpi.c -o mpi.o
	$(CC) $(CFLAGS) -DTESTING -DTIMER demo/demo.c mpi.o -o ltmtest
	./ltmtest
	rm -f *.o ltmtest
	$(CC) $(CFLAGS) -prof_use -ip -DTESTING -c mpi.c -o mpi.o
	$(AR) $(ARFLAGS) libtommath.a mpi.o
	ranlib libtommath.a	

install: libtommath.a
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
	install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
	install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)

test: libtommath.a demo/demo.o
	$(CC) demo/demo.o libtommath.a -o test
	
mtest: test	
	cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest
        
timing: libtommath.a
	$(CC) $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest

clean:
	rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
        *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.il etc/*.il *.dyn
	cd etc ; make clean
	cd pics ; make clean

Added libtommath/mess.sh.









>
>
>
>
1
2
3
4
#!/bin/bash
if cvs log $1 >/dev/null 2>/dev/null; then exit 0; else echo "$1 shouldn't be here" ; exit 1; fi


Added libtommath/mtest/logtab.h.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const float s_logv_2[] = {
   0.000000000, 0.000000000, 1.000000000, 0.630929754, 	/*  0  1  2  3 */
   0.500000000, 0.430676558, 0.386852807, 0.356207187, 	/*  4  5  6  7 */
   0.333333333, 0.315464877, 0.301029996, 0.289064826, 	/*  8  9 10 11 */
   0.278942946, 0.270238154, 0.262649535, 0.255958025, 	/* 12 13 14 15 */
   0.250000000, 0.244650542, 0.239812467, 0.235408913, 	/* 16 17 18 19 */
   0.231378213, 0.227670249, 0.224243824, 0.221064729, 	/* 20 21 22 23 */
   0.218104292, 0.215338279, 0.212746054, 0.210309918, 	/* 24 25 26 27 */
   0.208014598, 0.205846832, 0.203795047, 0.201849087, 	/* 28 29 30 31 */
   0.200000000, 0.198239863, 0.196561632, 0.194959022, 	/* 32 33 34 35 */
   0.193426404, 0.191958720, 0.190551412, 0.189200360, 	/* 36 37 38 39 */
   0.187901825, 0.186652411, 0.185449023, 0.184288833, 	/* 40 41 42 43 */
   0.183169251, 0.182087900, 0.181042597, 0.180031327, 	/* 44 45 46 47 */
   0.179052232, 0.178103594, 0.177183820, 0.176291434, 	/* 48 49 50 51 */
   0.175425064, 0.174583430, 0.173765343, 0.172969690, 	/* 52 53 54 55 */
   0.172195434, 0.171441601, 0.170707280, 0.169991616, 	/* 56 57 58 59 */
   0.169293808, 0.168613099, 0.167948779, 0.167300179, 	/* 60 61 62 63 */
   0.166666667
};

Added libtommath/mtest/mpi-config.h.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/* Default configuration for MPI library */

#ifndef MPI_CONFIG_H_
#define MPI_CONFIG_H_

/*
  For boolean options, 
  0 = no
  1 = yes

  Other options are documented individually.

 */

#ifndef MP_IOFUNC
#define MP_IOFUNC     0  /* include mp_print() ?                */
#endif

#ifndef MP_MODARITH
#define MP_MODARITH   1  /* include modular arithmetic ?        */
#endif

#ifndef MP_NUMTH
#define MP_NUMTH      1  /* include number theoretic functions? */
#endif

#ifndef MP_LOGTAB
#define MP_LOGTAB     1  /* use table of logs instead of log()? */
#endif

#ifndef MP_MEMSET
#define MP_MEMSET     1  /* use memset() to zero buffers?       */
#endif

#ifndef MP_MEMCPY
#define MP_MEMCPY     1  /* use memcpy() to copy buffers?       */
#endif

#ifndef MP_CRYPTO
#define MP_CRYPTO     1  /* erase memory on free?               */
#endif

#ifndef MP_ARGCHK
/*
  0 = no parameter checks
  1 = runtime checks, continue execution and return an error to caller
  2 = assertions; dump core on parameter errors
 */
#define MP_ARGCHK     2  /* how to check input arguments        */
#endif

#ifndef MP_DEBUG
#define MP_DEBUG      0  /* print diagnostic output?            */
#endif

#ifndef MP_DEFPREC
#define MP_DEFPREC    64 /* default precision, in digits        */
#endif

#ifndef MP_MACRO
#define MP_MACRO      1  /* use macros for frequent calls?      */
#endif

#ifndef MP_SQUARE
#define MP_SQUARE     1  /* use separate squaring code?         */
#endif

#ifndef MP_PTAB_SIZE
/*
  When building mpprime.c, we build in a table of small prime
  values to use for primality testing.  The more you include,
  the more space they take up.  See primes.c for the possible
  values (currently 16, 32, 64, 128, 256, and 6542)
 */
#define MP_PTAB_SIZE  128  /* how many built-in primes?         */
#endif

#ifndef MP_COMPAT_MACROS
#define MP_COMPAT_MACROS 1   /* define compatibility macros?    */
#endif

#endif /* ifndef MPI_CONFIG_H_ */


/* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */

Added libtommath/mtest/mpi-types.h.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Type definitions generated by 'types.pl' */
typedef char               mp_sign;
typedef unsigned short     mp_digit;  /* 2 byte type */
typedef unsigned int       mp_word;   /* 4 byte type */
typedef unsigned int       mp_size;
typedef int                mp_err;

#define MP_DIGIT_BIT       (CHAR_BIT*sizeof(mp_digit))
#define MP_DIGIT_MAX       USHRT_MAX
#define MP_WORD_BIT        (CHAR_BIT*sizeof(mp_word))
#define MP_WORD_MAX        UINT_MAX

#define MP_DIGIT_SIZE      2
#define DIGIT_FMT          "%04X"
#define RADIX              (MP_DIGIT_MAX+1)

Added libtommath/mtest/mpi.c.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
/*
    mpi.c

    by Michael J. Fromberger <[email protected]>
    Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved

    Arbitrary precision integer arithmetic library
 */

#include "mpi.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#if MP_DEBUG
#include <stdio.h>

#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
#else
#define DIAG(T,V)
#endif

/* 
   If MP_LOGTAB is not defined, use the math library to compute the
   logarithms on the fly.  Otherwise, use the static table below.
   Pick which works best for your system.
 */
#if MP_LOGTAB

/* {{{ s_logv_2[] - log table for 2 in various bases */

/*
  A table of the logs of 2 for various bases (the 0 and 1 entries of
  this table are meaningless and should not be referenced).  

  This table is used to compute output lengths for the mp_toradix()
  function.  Since a number n in radix r takes up about log_r(n)
  digits, we estimate the output size by taking the least integer
  greater than log_r(n), where:

  log_r(n) = log_2(n) * log_r(2)

  This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
  which are the output bases supported.  
 */

#include "logtab.h"

/* }}} */
#define LOG_V_2(R)  s_logv_2[(R)]

#else

#include <math.h>
#define LOG_V_2(R)  (log(2.0)/log(R))

#endif

/* Default precision for newly created mp_int's      */
static unsigned int s_mp_defprec = MP_DEFPREC;

/* {{{ Digit arithmetic macros */

/*
  When adding and multiplying digits, the results can be larger than
  can be contained in an mp_digit.  Thus, an mp_word is used.  These
  macros mask off the upper and lower digits of the mp_word (the
  mp_word may be more than 2 mp_digits wide, but we only concern
  ourselves with the low-order 2 mp_digits)

  If your mp_word DOES have more than 2 mp_digits, you need to
  uncomment the first line, and comment out the second.
 */

/* #define  CARRYOUT(W)  (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */
#define  CARRYOUT(W)  ((W)>>DIGIT_BIT)
#define  ACCUM(W)     ((W)&MP_DIGIT_MAX)

/* }}} */

/* {{{ Comparison constants */

#define  MP_LT       -1
#define  MP_EQ        0
#define  MP_GT        1

/* }}} */

/* {{{ Constant strings */

/* Constant strings returned by mp_strerror() */
static const char *mp_err_string[] = {
  "unknown result code",     /* say what?            */
  "boolean true",            /* MP_OKAY, MP_YES      */
  "boolean false",           /* MP_NO                */
  "out of memory",           /* MP_MEM               */
  "argument out of range",   /* MP_RANGE             */
  "invalid input parameter", /* MP_BADARG            */
  "result is undefined"      /* MP_UNDEF             */
};

/* Value to digit maps for radix conversion   */

/* s_dmap_1 - standard digits and letters */
static const char *s_dmap_1 = 
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";

#if 0
/* s_dmap_2 - base64 ordering for digits  */
static const char *s_dmap_2 =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#endif

/* }}} */

/* {{{ Static function declarations */

/* 
   If MP_MACRO is false, these will be defined as actual functions;
   otherwise, suitable macro definitions will be used.  This works
   around the fact that ANSI C89 doesn't support an 'inline' keyword
   (although I hear C9x will ... about bloody time).  At present, the
   macro definitions are identical to the function bodies, but they'll
   expand in place, instead of generating a function call.

   I chose these particular functions to be made into macros because
   some profiling showed they are called a lot on a typical workload,
   and yet they are primarily housekeeping.
 */
#if MP_MACRO == 0
 void     s_mp_setz(mp_digit *dp, mp_size count); /* zero digits           */
 void     s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy    */
 void    *s_mp_alloc(size_t nb, size_t ni);       /* general allocator     */
 void     s_mp_free(void *ptr);                   /* general free function */
#else

 /* Even if these are defined as macros, we need to respect the settings
    of the MP_MEMSET and MP_MEMCPY configuration options...
  */
 #if MP_MEMSET == 0
  #define  s_mp_setz(dp, count) \
       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
 #else
  #define  s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
 #endif /* MP_MEMSET */

 #if MP_MEMCPY == 0
  #define  s_mp_copy(sp, dp, count) \
       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
 #else
  #define  s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
 #endif /* MP_MEMCPY */

 #define  s_mp_alloc(nb, ni)  calloc(nb, ni)
 #define  s_mp_free(ptr) {if(ptr) free(ptr);}
#endif /* MP_MACRO */

mp_err   s_mp_grow(mp_int *mp, mp_size min);   /* increase allocated size */
mp_err   s_mp_pad(mp_int *mp, mp_size min);    /* left pad with zeroes    */

void     s_mp_clamp(mp_int *mp);               /* clip leading zeroes     */

void     s_mp_exch(mp_int *a, mp_int *b);      /* swap a and b in place   */

mp_err   s_mp_lshd(mp_int *mp, mp_size p);     /* left-shift by p digits  */
void     s_mp_rshd(mp_int *mp, mp_size p);     /* right-shift by p digits */
void     s_mp_div_2d(mp_int *mp, mp_digit d);  /* divide by 2^d in place  */
void     s_mp_mod_2d(mp_int *mp, mp_digit d);  /* modulo 2^d in place     */
mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d);  /* multiply by 2^d in place*/
void     s_mp_div_2(mp_int *mp);               /* divide by 2 in place    */
mp_err   s_mp_mul_2(mp_int *mp);               /* multiply by 2 in place  */
mp_digit s_mp_norm(mp_int *a, mp_int *b);      /* normalize for division  */
mp_err   s_mp_add_d(mp_int *mp, mp_digit d);   /* unsigned digit addition */
mp_err   s_mp_sub_d(mp_int *mp, mp_digit d);   /* unsigned digit subtract */
mp_err   s_mp_mul_d(mp_int *mp, mp_digit d);   /* unsigned digit multiply */
mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
		                               /* unsigned digit divide   */
mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
                                               /* Barrett reduction       */
mp_err   s_mp_add(mp_int *a, mp_int *b);       /* magnitude addition      */
mp_err   s_mp_sub(mp_int *a, mp_int *b);       /* magnitude subtract      */
mp_err   s_mp_mul(mp_int *a, mp_int *b);       /* magnitude multiply      */
#if 0
void     s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len);
                                               /* multiply buffers in place */
#endif
#if MP_SQUARE
mp_err   s_mp_sqr(mp_int *a);                  /* magnitude square        */
#else
#define  s_mp_sqr(a) s_mp_mul(a, a)
#endif
mp_err   s_mp_div(mp_int *a, mp_int *b);       /* magnitude divide        */
mp_err   s_mp_2expt(mp_int *a, mp_digit k);    /* a = 2^k                 */
int      s_mp_cmp(mp_int *a, mp_int *b);       /* magnitude comparison    */
int      s_mp_cmp_d(mp_int *a, mp_digit d);    /* magnitude digit compare */
int      s_mp_ispow2(mp_int *v);               /* is v a power of 2?      */
int      s_mp_ispow2d(mp_digit d);             /* is d a power of 2?      */

int      s_mp_tovalue(char ch, int r);          /* convert ch to value    */
char     s_mp_todigit(int val, int r, int low); /* convert val to digit   */
int      s_mp_outlen(int bits, int r);          /* output length in bytes */

/* }}} */

/* {{{ Default precision manipulation */

unsigned int mp_get_prec(void)
{
  return s_mp_defprec;

} /* end mp_get_prec() */

void         mp_set_prec(unsigned int prec)
{
  if(prec == 0)
    s_mp_defprec = MP_DEFPREC;
  else
    s_mp_defprec = prec;

} /* end mp_set_prec() */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ mp_init(mp) */

/*
  mp_init(mp)

  Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
  MP_MEM if memory could not be allocated for the structure.
 */

mp_err mp_init(mp_int *mp)
{
  return mp_init_size(mp, s_mp_defprec);

} /* end mp_init() */

/* }}} */

/* {{{ mp_init_array(mp[], count) */

mp_err mp_init_array(mp_int mp[], int count)
{
  mp_err  res;
  int     pos;

  ARGCHK(mp !=NULL && count > 0, MP_BADARG);

  for(pos = 0; pos < count; ++pos) {
    if((res = mp_init(&mp[pos])) != MP_OKAY)
      goto CLEANUP;
  }

  return MP_OKAY;

 CLEANUP:
  while(--pos >= 0) 
    mp_clear(&mp[pos]);

  return res;

} /* end mp_init_array() */

/* }}} */

/* {{{ mp_init_size(mp, prec) */

/*
  mp_init_size(mp, prec)

  Initialize a new zero-valued mp_int with at least the given
  precision; returns MP_OKAY if successful, or MP_MEM if memory could
  not be allocated for the structure.
 */

mp_err mp_init_size(mp_int *mp, mp_size prec)
{
  ARGCHK(mp != NULL && prec > 0, MP_BADARG);

  if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)
    return MP_MEM;

  SIGN(mp) = MP_ZPOS;
  USED(mp) = 1;
  ALLOC(mp) = prec;

  return MP_OKAY;

} /* end mp_init_size() */

/* }}} */

/* {{{ mp_init_copy(mp, from) */

/*
  mp_init_copy(mp, from)

  Initialize mp as an exact copy of from.  Returns MP_OKAY if
  successful, MP_MEM if memory could not be allocated for the new
  structure.
 */

mp_err mp_init_copy(mp_int *mp, mp_int *from)
{
  ARGCHK(mp != NULL && from != NULL, MP_BADARG);

  if(mp == from)
    return MP_OKAY;

  if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
    return MP_MEM;

  s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
  USED(mp) = USED(from);
  ALLOC(mp) = USED(from);
  SIGN(mp) = SIGN(from);

  return MP_OKAY;

} /* end mp_init_copy() */

/* }}} */

/* {{{ mp_copy(from, to) */

/*
  mp_copy(from, to)

  Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
  'to' has already been initialized (if not, use mp_init_copy()
  instead). If 'from' and 'to' are identical, nothing happens.
 */

mp_err mp_copy(mp_int *from, mp_int *to)
{
  ARGCHK(from != NULL && to != NULL, MP_BADARG);

  if(from == to)
    return MP_OKAY;

  { /* copy */
    mp_digit   *tmp;

    /*
      If the allocated buffer in 'to' already has enough space to hold
      all the used digits of 'from', we'll re-use it to avoid hitting
      the memory allocater more than necessary; otherwise, we'd have
      to grow anyway, so we just allocate a hunk and make the copy as
      usual
     */
    if(ALLOC(to) >= USED(from)) {
      s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
      s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
      
    } else {
      if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
	return MP_MEM;

      s_mp_copy(DIGITS(from), tmp, USED(from));

      if(DIGITS(to) != NULL) {
#if MP_CRYPTO
	s_mp_setz(DIGITS(to), ALLOC(to));
#endif
	s_mp_free(DIGITS(to));
      }

      DIGITS(to) = tmp;
      ALLOC(to) = USED(from);
    }

    /* Copy the precision and sign from the original */
    USED(to) = USED(from);
    SIGN(to) = SIGN(from);
  } /* end copy */

  return MP_OKAY;

} /* end mp_copy() */

/* }}} */

/* {{{ mp_exch(mp1, mp2) */

/*
  mp_exch(mp1, mp2)

  Exchange mp1 and mp2 without allocating any intermediate memory
  (well, unless you count the stack space needed for this call and the
  locals it creates...).  This cannot fail.
 */

void mp_exch(mp_int *mp1, mp_int *mp2)
{
#if MP_ARGCHK == 2
  assert(mp1 != NULL && mp2 != NULL);
#else
  if(mp1 == NULL || mp2 == NULL)
    return;
#endif

  s_mp_exch(mp1, mp2);

} /* end mp_exch() */

/* }}} */

/* {{{ mp_clear(mp) */

/*
  mp_clear(mp)

  Release the storage used by an mp_int, and void its fields so that
  if someone calls mp_clear() again for the same int later, we won't
  get tollchocked.
 */

void   mp_clear(mp_int *mp)
{
  if(mp == NULL)
    return;

  if(DIGITS(mp) != NULL) {
#if MP_CRYPTO
    s_mp_setz(DIGITS(mp), ALLOC(mp));
#endif
    s_mp_free(DIGITS(mp));
    DIGITS(mp) = NULL;
  }

  USED(mp) = 0;
  ALLOC(mp) = 0;

} /* end mp_clear() */

/* }}} */

/* {{{ mp_clear_array(mp[], count) */

void   mp_clear_array(mp_int mp[], int count)
{
  ARGCHK(mp != NULL && count > 0, MP_BADARG);

  while(--count >= 0) 
    mp_clear(&mp[count]);

} /* end mp_clear_array() */

/* }}} */

/* {{{ mp_zero(mp) */

/*
  mp_zero(mp) 

  Set mp to zero.  Does not change the allocated size of the structure,
  and therefore cannot fail (except on a bad argument, which we ignore)
 */
void   mp_zero(mp_int *mp)
{
  if(mp == NULL)
    return;

  s_mp_setz(DIGITS(mp), ALLOC(mp));
  USED(mp) = 1;
  SIGN(mp) = MP_ZPOS;

} /* end mp_zero() */

/* }}} */

/* {{{ mp_set(mp, d) */

void   mp_set(mp_int *mp, mp_digit d)
{
  if(mp == NULL)
    return;

  mp_zero(mp);
  DIGIT(mp, 0) = d;

} /* end mp_set() */

/* }}} */

/* {{{ mp_set_int(mp, z) */

mp_err mp_set_int(mp_int *mp, long z)
{
  int            ix;
  unsigned long  v = abs(z);
  mp_err         res;

  ARGCHK(mp != NULL, MP_BADARG);

  mp_zero(mp);
  if(z == 0)
    return MP_OKAY;  /* shortcut for zero */

  for(ix = sizeof(long) - 1; ix >= 0; ix--) {

    if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
      return res;

    res = s_mp_add_d(mp, 
		     (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
    if(res != MP_OKAY)
      return res;

  }

  if(z < 0)
    SIGN(mp) = MP_NEG;

  return MP_OKAY;

} /* end mp_set_int() */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ Digit arithmetic */

/* {{{ mp_add_d(a, d, b) */

/*
  mp_add_d(a, d, b)

  Compute the sum b = a + d, for a single digit d.  Respects the sign of
  its primary addend (single digits are unsigned anyway).
 */

mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b)
{
  mp_err   res = MP_OKAY;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  if(SIGN(b) == MP_ZPOS) {
    res = s_mp_add_d(b, d);
  } else if(s_mp_cmp_d(b, d) >= 0) {
    res = s_mp_sub_d(b, d);
  } else {
    SIGN(b) = MP_ZPOS;

    DIGIT(b, 0) = d - DIGIT(b, 0);
  }

  return res;

} /* end mp_add_d() */

/* }}} */

/* {{{ mp_sub_d(a, d, b) */

/*
  mp_sub_d(a, d, b)

  Compute the difference b = a - d, for a single digit d.  Respects the
  sign of its subtrahend (single digits are unsigned anyway).
 */

mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b)
{
  mp_err   res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  if(SIGN(b) == MP_NEG) {
    if((res = s_mp_add_d(b, d)) != MP_OKAY)
      return res;

  } else if(s_mp_cmp_d(b, d) >= 0) {
    if((res = s_mp_sub_d(b, d)) != MP_OKAY)
      return res;

  } else {
    mp_neg(b, b);

    DIGIT(b, 0) = d - DIGIT(b, 0);
    SIGN(b) = MP_NEG;
  }

  if(s_mp_cmp_d(b, 0) == 0)
    SIGN(b) = MP_ZPOS;

  return MP_OKAY;

} /* end mp_sub_d() */

/* }}} */

/* {{{ mp_mul_d(a, d, b) */

/*
  mp_mul_d(a, d, b)

  Compute the product b = a * d, for a single digit d.  Respects the sign
  of its multiplicand (single digits are unsigned anyway)
 */

mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b)
{
  mp_err  res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if(d == 0) {
    mp_zero(b);
    return MP_OKAY;
  }

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  res = s_mp_mul_d(b, d);

  return res;

} /* end mp_mul_d() */

/* }}} */

/* {{{ mp_mul_2(a, c) */

mp_err mp_mul_2(mp_int *a, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if((res = mp_copy(a, c)) != MP_OKAY)
    return res;

  return s_mp_mul_2(c);

} /* end mp_mul_2() */

/* }}} */

/* {{{ mp_div_d(a, d, q, r) */

/*
  mp_div_d(a, d, q, r)

  Compute the quotient q = a / d and remainder r = a mod d, for a
  single digit d.  Respects the sign of its divisor (single digits are
  unsigned anyway).
 */

mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
{
  mp_err   res;
  mp_digit rem;
  int      pow;

  ARGCHK(a != NULL, MP_BADARG);

  if(d == 0)
    return MP_RANGE;

  /* Shortcut for powers of two ... */
  if((pow = s_mp_ispow2d(d)) >= 0) {
    mp_digit  mask;

    mask = (1 << pow) - 1;
    rem = DIGIT(a, 0) & mask;

    if(q) {
      mp_copy(a, q);
      s_mp_div_2d(q, pow);
    }

    if(r)
      *r = rem;

    return MP_OKAY;
  }

  /*
    If the quotient is actually going to be returned, we'll try to
    avoid hitting the memory allocator by copying the dividend into it
    and doing the division there.  This can't be any _worse_ than
    always copying, and will sometimes be better (since it won't make
    another copy)

    If it's not going to be returned, we need to allocate a temporary
    to hold the quotient, which will just be discarded.
   */
  if(q) {
    if((res = mp_copy(a, q)) != MP_OKAY)
      return res;

    res = s_mp_div_d(q, d, &rem);
    if(s_mp_cmp_d(q, 0) == MP_EQ)
      SIGN(q) = MP_ZPOS;

  } else {
    mp_int  qp;

    if((res = mp_init_copy(&qp, a)) != MP_OKAY)
      return res;

    res = s_mp_div_d(&qp, d, &rem);
    if(s_mp_cmp_d(&qp, 0) == 0)
      SIGN(&qp) = MP_ZPOS;

    mp_clear(&qp);
  }

  if(r)
    *r = rem;

  return res;

} /* end mp_div_d() */

/* }}} */

/* {{{ mp_div_2(a, c) */

/*
  mp_div_2(a, c)

  Compute c = a / 2, disregarding the remainder.
 */

mp_err mp_div_2(mp_int *a, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if((res = mp_copy(a, c)) != MP_OKAY)
    return res;

  s_mp_div_2(c);

  return MP_OKAY;

} /* end mp_div_2() */

/* }}} */

/* {{{ mp_expt_d(a, d, b) */

mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c)
{
  mp_int   s, x;
  mp_err   res;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if((res = mp_init(&s)) != MP_OKAY)
    return res;
  if((res = mp_init_copy(&x, a)) != MP_OKAY)
    goto X;

  DIGIT(&s, 0) = 1;

  while(d != 0) {
    if(d & 1) {
      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
	goto CLEANUP;
    }

    d >>= 1;

    if((res = s_mp_sqr(&x)) != MP_OKAY)
      goto CLEANUP;
  }

  s_mp_exch(&s, c);

CLEANUP:
  mp_clear(&x);
X:
  mp_clear(&s);

  return res;

} /* end mp_expt_d() */

/* }}} */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ Full arithmetic */

/* {{{ mp_abs(a, b) */

/*
  mp_abs(a, b)

  Compute b = |a|.  'a' and 'b' may be identical.
 */

mp_err mp_abs(mp_int *a, mp_int *b)
{
  mp_err   res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  SIGN(b) = MP_ZPOS;

  return MP_OKAY;

} /* end mp_abs() */

/* }}} */

/* {{{ mp_neg(a, b) */

/*
  mp_neg(a, b)

  Compute b = -a.  'a' and 'b' may be identical.
 */

mp_err mp_neg(mp_int *a, mp_int *b)
{
  mp_err   res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  if(s_mp_cmp_d(b, 0) == MP_EQ) 
    SIGN(b) = MP_ZPOS;
  else 
    SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG;

  return MP_OKAY;

} /* end mp_neg() */

/* }}} */

/* {{{ mp_add(a, b, c) */

/*
  mp_add(a, b, c)

  Compute c = a + b.  All parameters may be identical.
 */

mp_err mp_add(mp_int *a, mp_int *b, mp_int *c)
{
  mp_err  res;
  int     cmp;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */

    /* Commutativity of addition lets us do this in either order,
       so we avoid having to use a temporary even if the result 
       is supposed to replace the output
     */
    if(c == b) {
      if((res = s_mp_add(c, a)) != MP_OKAY)
	return res;
    } else {
      if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
	return res;

      if((res = s_mp_add(c, b)) != MP_OKAY) 
	return res;
    }

  } else if((cmp = s_mp_cmp(a, b)) > 0) {  /* different sign: a > b   */

    /* If the output is going to be clobbered, we will use a temporary
       variable; otherwise, we'll do it without touching the memory 
       allocator at all, if possible
     */
    if(c == b) {
      mp_int  tmp;

      if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
	return res;
      if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
	mp_clear(&tmp);
	return res;
      }

      s_mp_exch(&tmp, c);
      mp_clear(&tmp);

    } else {

      if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
	return res;
      if((res = s_mp_sub(c, b)) != MP_OKAY)
	return res;

    }

  } else if(cmp == 0) {             /* different sign, a == b   */

    mp_zero(c);
    return MP_OKAY;

  } else {                          /* different sign: a < b    */

    /* See above... */
    if(c == a) {
      mp_int  tmp;

      if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
	return res;
      if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
	mp_clear(&tmp);
	return res;
      }

      s_mp_exch(&tmp, c);
      mp_clear(&tmp);

    } else {

      if(c != b && (res = mp_copy(b, c)) != MP_OKAY)
	return res;
      if((res = s_mp_sub(c, a)) != MP_OKAY)
	return res;

    }
  }

  if(USED(c) == 1 && DIGIT(c, 0) == 0)
    SIGN(c) = MP_ZPOS;

  return MP_OKAY;

} /* end mp_add() */

/* }}} */

/* {{{ mp_sub(a, b, c) */

/*
  mp_sub(a, b, c)

  Compute c = a - b.  All parameters may be identical.
 */

mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c)
{
  mp_err  res;
  int     cmp;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  if(SIGN(a) != SIGN(b)) {
    if(c == a) {
      if((res = s_mp_add(c, b)) != MP_OKAY)
	return res;
    } else {
      if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
	return res;
      if((res = s_mp_add(c, a)) != MP_OKAY)
	return res;
      SIGN(c) = SIGN(a);
    }

  } else if((cmp = s_mp_cmp(a, b)) > 0) { /* Same sign, a > b */
    if(c == b) {
      mp_int  tmp;

      if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
	return res;
      if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
	mp_clear(&tmp);
	return res;
      }
      s_mp_exch(&tmp, c);
      mp_clear(&tmp);

    } else {
      if(c != a && ((res = mp_copy(a, c)) != MP_OKAY))
	return res;

      if((res = s_mp_sub(c, b)) != MP_OKAY)
	return res;
    }

  } else if(cmp == 0) {  /* Same sign, equal magnitude */
    mp_zero(c);
    return MP_OKAY;

  } else {               /* Same sign, b > a */
    if(c == a) {
      mp_int  tmp;

      if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
	return res;

      if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
	mp_clear(&tmp);
	return res;
      }
      s_mp_exch(&tmp, c);
      mp_clear(&tmp);

    } else {
      if(c != b && ((res = mp_copy(b, c)) != MP_OKAY)) 
	return res;

      if((res = s_mp_sub(c, a)) != MP_OKAY)
	return res;
    }

    SIGN(c) = !SIGN(b);
  }

  if(USED(c) == 1 && DIGIT(c, 0) == 0)
    SIGN(c) = MP_ZPOS;

  return MP_OKAY;

} /* end mp_sub() */

/* }}} */

/* {{{ mp_mul(a, b, c) */

/*
  mp_mul(a, b, c)

  Compute c = a * b.  All parameters may be identical.
 */

mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c)
{
  mp_err   res;
  mp_sign  sgn;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG;

  if(c == b) {
    if((res = s_mp_mul(c, a)) != MP_OKAY)
      return res;

  } else {
    if((res = mp_copy(a, c)) != MP_OKAY)
      return res;

    if((res = s_mp_mul(c, b)) != MP_OKAY)
      return res;
  }
  
  if(sgn == MP_ZPOS || s_mp_cmp_d(c, 0) == MP_EQ)
    SIGN(c) = MP_ZPOS;
  else
    SIGN(c) = sgn;
  
  return MP_OKAY;

} /* end mp_mul() */

/* }}} */

/* {{{ mp_mul_2d(a, d, c) */

/*
  mp_mul_2d(a, d, c)

  Compute c = a * 2^d.  a may be the same as c.
 */

mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c)
{
  mp_err   res;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if((res = mp_copy(a, c)) != MP_OKAY)
    return res;

  if(d == 0)
    return MP_OKAY;

  return s_mp_mul_2d(c, d);

} /* end mp_mul() */

/* }}} */

/* {{{ mp_sqr(a, b) */

#if MP_SQUARE
mp_err mp_sqr(mp_int *a, mp_int *b)
{
  mp_err   res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if((res = mp_copy(a, b)) != MP_OKAY)
    return res;

  if((res = s_mp_sqr(b)) != MP_OKAY)
    return res;

  SIGN(b) = MP_ZPOS;

  return MP_OKAY;

} /* end mp_sqr() */
#endif

/* }}} */

/* {{{ mp_div(a, b, q, r) */

/*
  mp_div(a, b, q, r)

  Compute q = a / b and r = a mod b.  Input parameters may be re-used
  as output parameters.  If q or r is NULL, that portion of the
  computation will be discarded (although it will still be computed)

  Pay no attention to the hacker behind the curtain.
 */

mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
{
  mp_err   res;
  mp_int   qtmp, rtmp;
  int      cmp;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  if(mp_cmp_z(b) == MP_EQ)
    return MP_RANGE;

  /* If a <= b, we can compute the solution without division, and
     avoid any memory allocation
   */
  if((cmp = s_mp_cmp(a, b)) < 0) {
    if(r) {
      if((res = mp_copy(a, r)) != MP_OKAY)
	return res;
    }

    if(q) 
      mp_zero(q);

    return MP_OKAY;

  } else if(cmp == 0) {

    /* Set quotient to 1, with appropriate sign */
    if(q) {
      int qneg = (SIGN(a) != SIGN(b));

      mp_set(q, 1);
      if(qneg)
	SIGN(q) = MP_NEG;
    }

    if(r)
      mp_zero(r);

    return MP_OKAY;
  }

  /* If we get here, it means we actually have to do some division */

  /* Set up some temporaries... */
  if((res = mp_init_copy(&qtmp, a)) != MP_OKAY)
    return res;
  if((res = mp_init_copy(&rtmp, b)) != MP_OKAY)
    goto CLEANUP;

  if((res = s_mp_div(&qtmp, &rtmp)) != MP_OKAY)
    goto CLEANUP;

  /* Compute the signs for the output  */
  SIGN(&rtmp) = SIGN(a); /* Sr = Sa              */
  if(SIGN(a) == SIGN(b))
    SIGN(&qtmp) = MP_ZPOS;  /* Sq = MP_ZPOS if Sa = Sb */
  else
    SIGN(&qtmp) = MP_NEG;   /* Sq = MP_NEG if Sa != Sb */

  if(s_mp_cmp_d(&qtmp, 0) == MP_EQ)
    SIGN(&qtmp) = MP_ZPOS;
  if(s_mp_cmp_d(&rtmp, 0) == MP_EQ)
    SIGN(&rtmp) = MP_ZPOS;

  /* Copy output, if it is needed      */
  if(q) 
    s_mp_exch(&qtmp, q);

  if(r) 
    s_mp_exch(&rtmp, r);

CLEANUP:
  mp_clear(&rtmp);
  mp_clear(&qtmp);

  return res;

} /* end mp_div() */

/* }}} */

/* {{{ mp_div_2d(a, d, q, r) */

mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r)
{
  mp_err  res;

  ARGCHK(a != NULL, MP_BADARG);

  if(q) {
    if((res = mp_copy(a, q)) != MP_OKAY)
      return res;

    s_mp_div_2d(q, d);
  }

  if(r) {
    if((res = mp_copy(a, r)) != MP_OKAY)
      return res;

    s_mp_mod_2d(r, d);
  }

  return MP_OKAY;

} /* end mp_div_2d() */

/* }}} */

/* {{{ mp_expt(a, b, c) */

/*
  mp_expt(a, b, c)

  Compute c = a ** b, that is, raise a to the b power.  Uses a
  standard iterative square-and-multiply technique.
 */

mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
{
  mp_int   s, x;
  mp_err   res;
  mp_digit d;
  int      dig, bit;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  if(mp_cmp_z(b) < 0)
    return MP_RANGE;

  if((res = mp_init(&s)) != MP_OKAY)
    return res;

  mp_set(&s, 1);

  if((res = mp_init_copy(&x, a)) != MP_OKAY)
    goto X;

  /* Loop over low-order digits in ascending order */
  for(dig = 0; dig < (USED(b) - 1); dig++) {
    d = DIGIT(b, dig);

    /* Loop over bits of each non-maximal digit */
    for(bit = 0; bit < DIGIT_BIT; bit++) {
      if(d & 1) {
	if((res = s_mp_mul(&s, &x)) != MP_OKAY) 
	  goto CLEANUP;
      }

      d >>= 1;
      
      if((res = s_mp_sqr(&x)) != MP_OKAY)
	goto CLEANUP;
    }
  }

  /* Consider now the last digit... */
  d = DIGIT(b, dig);

  while(d) {
    if(d & 1) {
      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
	goto CLEANUP;
    }

    d >>= 1;

    if((res = s_mp_sqr(&x)) != MP_OKAY)
      goto CLEANUP;
  }
  
  if(mp_iseven(b))
    SIGN(&s) = SIGN(a);

  res = mp_copy(&s, c);

CLEANUP:
  mp_clear(&x);
X:
  mp_clear(&s);

  return res;

} /* end mp_expt() */

/* }}} */

/* {{{ mp_2expt(a, k) */

/* Compute a = 2^k */

mp_err mp_2expt(mp_int *a, mp_digit k)
{
  ARGCHK(a != NULL, MP_BADARG);

  return s_mp_2expt(a, k);

} /* end mp_2expt() */

/* }}} */

/* {{{ mp_mod(a, m, c) */

/*
  mp_mod(a, m, c)

  Compute c = a (mod m).  Result will always be 0 <= c < m.
 */

mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c)
{
  mp_err  res;
  int     mag;

  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);

  if(SIGN(m) == MP_NEG)
    return MP_RANGE;

  /*
     If |a| > m, we need to divide to get the remainder and take the
     absolute value.  

     If |a| < m, we don't need to do any division, just copy and adjust
     the sign (if a is negative).

     If |a| == m, we can simply set the result to zero.

     This order is intended to minimize the average path length of the
     comparison chain on common workloads -- the most frequent cases are
     that |a| != m, so we do those first.
   */
  if((mag = s_mp_cmp(a, m)) > 0) {
    if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
      return res;
    
    if(SIGN(c) == MP_NEG) {
      if((res = mp_add(c, m, c)) != MP_OKAY)
	return res;
    }

  } else if(mag < 0) {
    if((res = mp_copy(a, c)) != MP_OKAY)
      return res;

    if(mp_cmp_z(a) < 0) {
      if((res = mp_add(c, m, c)) != MP_OKAY)
	return res;

    }
    
  } else {
    mp_zero(c);

  }

  return MP_OKAY;

} /* end mp_mod() */

/* }}} */

/* {{{ mp_mod_d(a, d, c) */

/*
  mp_mod_d(a, d, c)

  Compute c = a (mod d).  Result will always be 0 <= c < d
 */
mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c)
{
  mp_err   res;
  mp_digit rem;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if(s_mp_cmp_d(a, d) > 0) {
    if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
      return res;

  } else {
    if(SIGN(a) == MP_NEG)
      rem = d - DIGIT(a, 0);
    else
      rem = DIGIT(a, 0);
  }

  if(c)
    *c = rem;

  return MP_OKAY;

} /* end mp_mod_d() */

/* }}} */

/* {{{ mp_sqrt(a, b) */

/*
  mp_sqrt(a, b)

  Compute the integer square root of a, and store the result in b.
  Uses an integer-arithmetic version of Newton's iterative linear
  approximation technique to determine this value; the result has the
  following two properties:

     b^2 <= a
     (b+1)^2 >= a

  It is a range error to pass a negative value.
 */
mp_err mp_sqrt(mp_int *a, mp_int *b)
{
  mp_int   x, t;
  mp_err   res;

  ARGCHK(a != NULL && b != NULL, MP_BADARG);

  /* Cannot take square root of a negative value */
  if(SIGN(a) == MP_NEG)
    return MP_RANGE;

  /* Special cases for zero and one, trivial     */
  if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ) 
    return mp_copy(a, b);
    
  /* Initialize the temporaries we'll use below  */
  if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
    return res;

  /* Compute an initial guess for the iteration as a itself */
  if((res = mp_init_copy(&x, a)) != MP_OKAY)
    goto X;

s_mp_rshd(&x, (USED(&x)/2)+1);
mp_add_d(&x, 1, &x);

  for(;;) {
    /* t = (x * x) - a */
    mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
    if((res = mp_sqr(&t, &t)) != MP_OKAY ||
       (res = mp_sub(&t, a, &t)) != MP_OKAY)
      goto CLEANUP;

    /* t = t / 2x       */
    s_mp_mul_2(&x);
    if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
      goto CLEANUP;
    s_mp_div_2(&x);

    /* Terminate the loop, if the quotient is zero */
    if(mp_cmp_z(&t) == MP_EQ)
      break;

    /* x = x - t       */
    if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
      goto CLEANUP;

  }

  /* Copy result to output parameter */
  mp_sub_d(&x, 1, &x);
  s_mp_exch(&x, b);

 CLEANUP:
  mp_clear(&x);
 X:
  mp_clear(&t); 

  return res;

} /* end mp_sqrt() */

/* }}} */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ Modular arithmetic */

#if MP_MODARITH
/* {{{ mp_addmod(a, b, m, c) */

/*
  mp_addmod(a, b, m, c)

  Compute c = (a + b) mod m
 */

mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);

  if((res = mp_add(a, b, c)) != MP_OKAY)
    return res;
  if((res = mp_mod(c, m, c)) != MP_OKAY)
    return res;

  return MP_OKAY;

}

/* }}} */

/* {{{ mp_submod(a, b, m, c) */

/*
  mp_submod(a, b, m, c)

  Compute c = (a - b) mod m
 */

mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);

  if((res = mp_sub(a, b, c)) != MP_OKAY)
    return res;
  if((res = mp_mod(c, m, c)) != MP_OKAY)
    return res;

  return MP_OKAY;

}

/* }}} */

/* {{{ mp_mulmod(a, b, m, c) */

/*
  mp_mulmod(a, b, m, c)

  Compute c = (a * b) mod m
 */

mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);

  if((res = mp_mul(a, b, c)) != MP_OKAY)
    return res;
  if((res = mp_mod(c, m, c)) != MP_OKAY)
    return res;

  return MP_OKAY;

}

/* }}} */

/* {{{ mp_sqrmod(a, m, c) */

#if MP_SQUARE
mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
{
  mp_err  res;

  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);

  if((res = mp_sqr(a, c)) != MP_OKAY)
    return res;
  if((res = mp_mod(c, m, c)) != MP_OKAY)
    return res;

  return MP_OKAY;

} /* end mp_sqrmod() */
#endif

/* }}} */

/* {{{ mp_exptmod(a, b, m, c) */

/*
  mp_exptmod(a, b, m, c)

  Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
  method with modular reductions at each step. (This is basically the
  same code as mp_expt(), except for the addition of the reductions)
  
  The modular reductions are done using Barrett's algorithm (see
  s_mp_reduce() below for details)
 */

mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
{
  mp_int   s, x, mu;
  mp_err   res;
  mp_digit d, *db = DIGITS(b);
  mp_size  ub = USED(b);
  int      dig, bit;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
    return MP_RANGE;

  if((res = mp_init(&s)) != MP_OKAY)
    return res;
  if((res = mp_init_copy(&x, a)) != MP_OKAY)
    goto X;
  if((res = mp_mod(&x, m, &x)) != MP_OKAY ||
     (res = mp_init(&mu)) != MP_OKAY)
    goto MU;

  mp_set(&s, 1);

  /* mu = b^2k / m */
  s_mp_add_d(&mu, 1); 
  s_mp_lshd(&mu, 2 * USED(m));
  if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
    goto CLEANUP;

  /* Loop over digits of b in ascending order, except highest order */
  for(dig = 0; dig < (ub - 1); dig++) {
    d = *db++;

    /* Loop over the bits of the lower-order digits */
    for(bit = 0; bit < DIGIT_BIT; bit++) {
      if(d & 1) {
	if((res = s_mp_mul(&s, &x)) != MP_OKAY)
	  goto CLEANUP;
	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
	  goto CLEANUP;
      }

      d >>= 1;

      if((res = s_mp_sqr(&x)) != MP_OKAY)
	goto CLEANUP;
      if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
	goto CLEANUP;
    }
  }

  /* Now do the last digit... */
  d = *db;

  while(d) {
    if(d & 1) {
      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
	goto CLEANUP;
      if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
	goto CLEANUP;
    }

    d >>= 1;

    if((res = s_mp_sqr(&x)) != MP_OKAY)
      goto CLEANUP;
    if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
      goto CLEANUP;
  }

  s_mp_exch(&s, c);

 CLEANUP:
  mp_clear(&mu);
 MU:
  mp_clear(&x);
 X:
  mp_clear(&s);

  return res;

} /* end mp_exptmod() */

/* }}} */

/* {{{ mp_exptmod_d(a, d, m, c) */

mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c)
{
  mp_int   s, x;
  mp_err   res;

  ARGCHK(a != NULL && c != NULL, MP_BADARG);

  if((res = mp_init(&s)) != MP_OKAY)
    return res;
  if((res = mp_init_copy(&x, a)) != MP_OKAY)
    goto X;

  mp_set(&s, 1);

  while(d != 0) {
    if(d & 1) {
      if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
	 (res = mp_mod(&s, m, &s)) != MP_OKAY)
	goto CLEANUP;
    }

    d /= 2;

    if((res = s_mp_sqr(&x)) != MP_OKAY ||
       (res = mp_mod(&x, m, &x)) != MP_OKAY)
      goto CLEANUP;
  }

  s_mp_exch(&s, c);

CLEANUP:
  mp_clear(&x);
X:
  mp_clear(&s);

  return res;

} /* end mp_exptmod_d() */

/* }}} */
#endif /* if MP_MODARITH */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ Comparison functions */

/* {{{ mp_cmp_z(a) */

/*
  mp_cmp_z(a)

  Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
 */

int    mp_cmp_z(mp_int *a)
{
  if(SIGN(a) == MP_NEG)
    return MP_LT;
  else if(USED(a) == 1 && DIGIT(a, 0) == 0)
    return MP_EQ;
  else
    return MP_GT;

} /* end mp_cmp_z() */

/* }}} */

/* {{{ mp_cmp_d(a, d) */

/*
  mp_cmp_d(a, d)

  Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
 */

int    mp_cmp_d(mp_int *a, mp_digit d)
{
  ARGCHK(a != NULL, MP_EQ);

  if(SIGN(a) == MP_NEG)
    return MP_LT;

  return s_mp_cmp_d(a, d);

} /* end mp_cmp_d() */

/* }}} */

/* {{{ mp_cmp(a, b) */

int    mp_cmp(mp_int *a, mp_int *b)
{
  ARGCHK(a != NULL && b != NULL, MP_EQ);

  if(SIGN(a) == SIGN(b)) {
    int  mag;

    if((mag = s_mp_cmp(a, b)) == MP_EQ)
      return MP_EQ;

    if(SIGN(a) == MP_ZPOS)
      return mag;
    else
      return -mag;

  } else if(SIGN(a) == MP_ZPOS) {
    return MP_GT;
  } else {
    return MP_LT;
  }

} /* end mp_cmp() */

/* }}} */

/* {{{ mp_cmp_mag(a, b) */

/*
  mp_cmp_mag(a, b)

  Compares |a| <=> |b|, and returns an appropriate comparison result
 */

int    mp_cmp_mag(mp_int *a, mp_int *b)
{
  ARGCHK(a != NULL && b != NULL, MP_EQ);

  return s_mp_cmp(a, b);

} /* end mp_cmp_mag() */

/* }}} */

/* {{{ mp_cmp_int(a, z) */

/*
  This just converts z to an mp_int, and uses the existing comparison
  routines.  This is sort of inefficient, but it's not clear to me how
  frequently this wil get used anyway.  For small positive constants,
  you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
 */
int    mp_cmp_int(mp_int *a, long z)
{
  mp_int  tmp;
  int     out;

  ARGCHK(a != NULL, MP_EQ);
  
  mp_init(&tmp); mp_set_int(&tmp, z);
  out = mp_cmp(a, &tmp);
  mp_clear(&tmp);

  return out;

} /* end mp_cmp_int() */

/* }}} */

/* {{{ mp_isodd(a) */

/*
  mp_isodd(a)

  Returns a true (non-zero) value if a is odd, false (zero) otherwise.
 */
int    mp_isodd(mp_int *a)
{
  ARGCHK(a != NULL, 0);

  return (DIGIT(a, 0) & 1);

} /* end mp_isodd() */

/* }}} */

/* {{{ mp_iseven(a) */

int    mp_iseven(mp_int *a)
{
  return !mp_isodd(a);

} /* end mp_iseven() */

/* }}} */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ Number theoretic functions */

#if MP_NUMTH
/* {{{ mp_gcd(a, b, c) */

/*
  Like the old mp_gcd() function, except computes the GCD using the
  binary algorithm due to Josef Stein in 1961 (via Knuth).
 */
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
{
  mp_err   res;
  mp_int   u, v, t;
  mp_size  k = 0;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
      return MP_RANGE;
  if(mp_cmp_z(a) == MP_EQ) {
    return mp_copy(b, c);
  } else if(mp_cmp_z(b) == MP_EQ) {
    return mp_copy(a, c);
  }

  if((res = mp_init(&t)) != MP_OKAY)
    return res;
  if((res = mp_init_copy(&u, a)) != MP_OKAY)
    goto U;
  if((res = mp_init_copy(&v, b)) != MP_OKAY)
    goto V;

  SIGN(&u) = MP_ZPOS;
  SIGN(&v) = MP_ZPOS;

  /* Divide out common factors of 2 until at least 1 of a, b is even */
  while(mp_iseven(&u) && mp_iseven(&v)) {
    s_mp_div_2(&u);
    s_mp_div_2(&v);
    ++k;
  }

  /* Initialize t */
  if(mp_isodd(&u)) {
    if((res = mp_copy(&v, &t)) != MP_OKAY)
      goto CLEANUP;
    
    /* t = -v */
    if(SIGN(&v) == MP_ZPOS)
      SIGN(&t) = MP_NEG;
    else
      SIGN(&t) = MP_ZPOS;
    
  } else {
    if((res = mp_copy(&u, &t)) != MP_OKAY)
      goto CLEANUP;

  }

  for(;;) {
    while(mp_iseven(&t)) {
      s_mp_div_2(&t);
    }

    if(mp_cmp_z(&t) == MP_GT) {
      if((res = mp_copy(&t, &u)) != MP_OKAY)
	goto CLEANUP;

    } else {
      if((res = mp_copy(&t, &v)) != MP_OKAY)
	goto CLEANUP;

      /* v = -t */
      if(SIGN(&t) == MP_ZPOS)
	SIGN(&v) = MP_NEG;
      else
	SIGN(&v) = MP_ZPOS;
    }

    if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
      goto CLEANUP;

    if(s_mp_cmp_d(&t, 0) == MP_EQ)
      break;
  }

  s_mp_2expt(&v, k);       /* v = 2^k   */
  res = mp_mul(&u, &v, c); /* c = u * v */

 CLEANUP:
  mp_clear(&v);
 V:
  mp_clear(&u);
 U:
  mp_clear(&t);

  return res;

} /* end mp_bgcd() */

/* }}} */

/* {{{ mp_lcm(a, b, c) */

/* We compute the least common multiple using the rule:

   ab = [a, b](a, b)

   ... by computing the product, and dividing out the gcd.
 */

mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
{
  mp_int  gcd, prod;
  mp_err  res;

  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

  /* Set up temporaries */
  if((res = mp_init(&gcd)) != MP_OKAY)
    return res;
  if((res = mp_init(&prod)) != MP_OKAY)
    goto GCD;

  if((res = mp_mul(a, b, &prod)) != MP_OKAY)
    goto CLEANUP;
  if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
    goto CLEANUP;

  res = mp_div(&prod, &gcd, c, NULL);

 CLEANUP:
  mp_clear(&prod);
 GCD:
  mp_clear(&gcd);

  return res;

} /* end mp_lcm() */

/* }}} */

/* {{{ mp_xgcd(a, b, g, x, y) */

/*
  mp_xgcd(a, b, g, x, y)

  Compute g = (a, b) and values x and y satisfying Bezout's identity
  (that is, ax + by = g).  This uses the extended binary GCD algorithm
  based on the Stein algorithm used for mp_gcd()
 */

mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y)
{
  mp_int   gx, xc, yc, u, v, A, B, C, D;
  mp_int  *clean[9];
  mp_err   res;
  int      last = -1;

  if(mp_cmp_z(b) == 0)
    return MP_RANGE;

  /* Initialize all these variables we need */
  if((res = mp_init(&u)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &u;
  if((res = mp_init(&v)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &v;
  if((res = mp_init(&gx)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &gx;
  if((res = mp_init(&A)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &A;
  if((res = mp_init(&B)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &B;
  if((res = mp_init(&C)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &C;
  if((res = mp_init(&D)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &D;
  if((res = mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &xc;
  mp_abs(&xc, &xc);
  if((res = mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP;
  clean[++last] = &yc;
  mp_abs(&yc, &yc);

  mp_set(&gx, 1);

  /* Divide by two until at least one of them is even */
  while(mp_iseven(&xc) && mp_iseven(&yc)) {
    s_mp_div_2(&xc);
    s_mp_div_2(&yc);
    if((res = s_mp_mul_2(&gx)) != MP_OKAY)
      goto CLEANUP;
  }

  mp_copy(&xc, &u);
  mp_copy(&yc, &v);
  mp_set(&A, 1); mp_set(&D, 1);

  /* Loop through binary GCD algorithm */
  for(;;) {
    while(mp_iseven(&u)) {
      s_mp_div_2(&u);

      if(mp_iseven(&A) && mp_iseven(&B)) {
	s_mp_div_2(&A); s_mp_div_2(&B);
      } else {
	if((res = mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP;
	s_mp_div_2(&A);
	if((res = mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP;
	s_mp_div_2(&B);
      }
    }

    while(mp_iseven(&v)) {
      s_mp_div_2(&v);

      if(mp_iseven(&C) && mp_iseven(&D)) {
	s_mp_div_2(&C); s_mp_div_2(&D);
      } else {
	if((res = mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP;
	s_mp_div_2(&C);
	if((res = mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP;
	s_mp_div_2(&D);
      }
    }

    if(mp_cmp(&u, &v) >= 0) {
      if((res = mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP;
      if((res = mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP;
      if((res = mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP;

    } else {
      if((res = mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP;
      if((res = mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP;
      if((res = mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP;

    }

    /* If we're done, copy results to output */
    if(mp_cmp_z(&u) == 0) {
      if(x)
	if((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP;

      if(y)
	if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP;
      
      if(g)
	if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP;

      break;
    }
  }

 CLEANUP:
  while(last >= 0)
    mp_clear(clean[last--]);

  return res;

} /* end mp_xgcd() */

/* }}} */

/* {{{ mp_invmod(a, m, c) */

/*
  mp_invmod(a, m, c)

  Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
  This is equivalent to the question of whether (a, m) = 1.  If not,
  MP_UNDEF is returned, and there is no inverse.
 */

mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c)
{
  mp_int  g, x;
  mp_err  res;

  ARGCHK(a && m && c, MP_BADARG);

  if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
    return MP_RANGE;

  if((res = mp_init(&g)) != MP_OKAY)
    return res;
  if((res = mp_init(&x)) != MP_OKAY)
    goto X;

  if((res = mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY)
    goto CLEANUP;

  if(mp_cmp_d(&g, 1) != MP_EQ) {
    res = MP_UNDEF;
    goto CLEANUP;
  }

  res = mp_mod(&x, m, c);
  SIGN(c) = SIGN(a);

CLEANUP:
  mp_clear(&x);
X:
  mp_clear(&g);

  return res;

} /* end mp_invmod() */

/* }}} */
#endif /* if MP_NUMTH */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ mp_print(mp, ofp) */

#if MP_IOFUNC
/*
  mp_print(mp, ofp)

  Print a textual representation of the given mp_int on the output
  stream 'ofp'.  Output is generated using the internal radix.
 */

void   mp_print(mp_int *mp, FILE *ofp)
{
  int   ix;

  if(mp == NULL || ofp == NULL)
    return;

  fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp);

  for(ix = USED(mp) - 1; ix >= 0; ix--) {
    fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
  }

} /* end mp_print() */

#endif /* if MP_IOFUNC */

/* }}} */

/*------------------------------------------------------------------------*/
/* {{{ More I/O Functions */

/* {{{ mp_read_signed_bin(mp, str, len) */

/* 
   mp_read_signed_bin(mp, str, len)

   Read in a raw value (base 256) into the given mp_int
 */

mp_err  mp_read_signed_bin(mp_int *mp, unsigned char *str, int len)
{
  mp_err         res;

  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);

  if((res = mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) {
    /* Get sign from first byte */
    if(str[0])
      SIGN(mp) = MP_NEG;
    else
      SIGN(mp) = MP_ZPOS;
  }

  return res;

} /* end mp_read_signed_bin() */

/* }}} */

/* {{{ mp_signed_bin_size(mp) */

int    mp_signed_bin_size(mp_int *mp)
{
  ARGCHK(mp != NULL, 0);

  return mp_unsigned_bin_size(mp) + 1;

} /* end mp_signed_bin_size() */

/* }}} */

/* {{{ mp_to_signed_bin(mp, str) */

mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str)
{
  ARGCHK(mp != NULL && str != NULL, MP_BADARG);

  /* Caller responsible for allocating enough memory (use mp_raw_size(mp)) */
  str[0] = (char)SIGN(mp);

  return mp_to_unsigned_bin(mp, str + 1);

} /* end mp_to_signed_bin() */

/* }}} */

/* {{{ mp_read_unsigned_bin(mp, str, len) */

/*
  mp_read_unsigned_bin(mp, str, len)

  Read in an unsigned value (base 256) into the given mp_int
 */

mp_err  mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len)
{
  int     ix;
  mp_err  res;

  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);

  mp_zero(mp);

  for(ix = 0; ix < len; ix++) {
    if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
      return res;

    if((res = mp_add_d(mp, str[ix], mp)) != MP_OKAY)
      return res;
  }
  
  return MP_OKAY;
  
} /* end mp_read_unsigned_bin() */

/* }}} */

/* {{{ mp_unsigned_bin_size(mp) */

int     mp_unsigned_bin_size(mp_int *mp) 
{
  mp_digit   topdig;
  int        count;

  ARGCHK(mp != NULL, 0);

  /* Special case for the value zero */
  if(USED(mp) == 1 && DIGIT(mp, 0) == 0)
    return 1;

  count = (USED(mp) - 1) * sizeof(mp_digit);
  topdig = DIGIT(mp, USED(mp) - 1);

  while(topdig != 0) {
    ++count;
    topdig >>= CHAR_BIT;
  }

  return count;

} /* end mp_unsigned_bin_size() */

/* }}} */

/* {{{ mp_to_unsigned_bin(mp, str) */

mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str)
{
  mp_digit      *dp, *end, d;
  unsigned char *spos;

  ARGCHK(mp != NULL && str != NULL, MP_BADARG);

  dp = DIGITS(mp);
  end = dp + USED(mp) - 1;
  spos = str;

  /* Special case for zero, quick test */
  if(dp == end && *dp == 0) {
    *str = '\0';
    return MP_OKAY;
  }

  /* Generate digits in reverse order */
  while(dp < end) {
    int      ix;

    d = *dp;
    for(ix = 0; ix < sizeof(mp_digit); ++ix) {
      *spos = d & UCHAR_MAX;
      d >>= CHAR_BIT;
      ++spos;
    }

    ++dp;
  }

  /* Now handle last digit specially, high order zeroes are not written */
  d = *end;
  while(d != 0) {
    *spos = d & UCHAR_MAX;
    d >>= CHAR_BIT;
    ++spos;
  }

  /* Reverse everything to get digits in the correct order */
  while(--spos > str) {
    unsigned char t = *str;
    *str = *spos;
    *spos = t;

    ++str;
  }

  return MP_OKAY;

} /* end mp_to_unsigned_bin() */

/* }}} */

/* {{{ mp_count_bits(mp) */

int    mp_count_bits(mp_int *mp)
{
  int      len;
  mp_digit d;

  ARGCHK(mp != NULL, MP_BADARG);

  len = DIGIT_BIT * (USED(mp) - 1);
  d = DIGIT(mp, USED(mp) - 1);

  while(d != 0) {
    ++len;
    d >>= 1;
  }

  return len;
  
} /* end mp_count_bits() */

/* }}} */

/* {{{ mp_read_radix(mp, str, radix) */

/*
  mp_read_radix(mp, str, radix)

  Read an integer from the given string, and set mp to the resulting
  value.  The input is presumed to be in base 10.  Leading non-digit
  characters are ignored, and the function reads until a non-digit
  character or the end of the string.
 */

mp_err  mp_read_radix(mp_int *mp, unsigned char *str, int radix)
{
  int     ix = 0, val = 0;
  mp_err  res;
  mp_sign sig = MP_ZPOS;

  ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, 
	 MP_BADARG);

  mp_zero(mp);

  /* Skip leading non-digit characters until a digit or '-' or '+' */
  while(str[ix] && 
	(s_mp_tovalue(str[ix], radix) < 0) && 
	str[ix] != '-' &&
	str[ix] != '+') {
    ++ix;
  }

  if(str[ix] == '-') {
    sig = MP_NEG;
    ++ix;
  } else if(str[ix] == '+') {
    sig = MP_ZPOS; /* this is the default anyway... */
    ++ix;
  }

  while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
    if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
      return res;
    if((res = s_mp_add_d(mp, val)) != MP_OKAY)
      return res;
    ++ix;
  }

  if(s_mp_cmp_d(mp, 0) == MP_EQ)
    SIGN(mp) = MP_ZPOS;
  else
    SIGN(mp) = sig;

  return MP_OKAY;

} /* end mp_read_radix() */

/* }}} */

/* {{{ mp_radix_size(mp, radix) */

int    mp_radix_size(mp_int *mp, int radix)
{
  int  len;
  ARGCHK(mp != NULL, 0);

  len = s_mp_outlen(mp_count_bits(mp), radix) + 1; /* for NUL terminator */

  if(mp_cmp_z(mp) < 0)
    ++len; /* for sign */

  return len;

} /* end mp_radix_size() */

/* }}} */

/* {{{ mp_value_radix_size(num, qty, radix) */

/* num = number of digits
   qty = number of bits per digit
   radix = target base
   
   Return the number of digits in the specified radix that would be
   needed to express 'num' digits of 'qty' bits each.
 */
int    mp_value_radix_size(int num, int qty, int radix)
{
  ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0);

  return s_mp_outlen(num * qty, radix);

} /* end mp_value_radix_size() */

/* }}} */

/* {{{ mp_toradix(mp, str, radix) */

mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix)
{
  int  ix, pos = 0;

  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
  ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);

  if(mp_cmp_z(mp) == MP_EQ) {
    str[0] = '0';
    str[1] = '\0';
  } else {
    mp_err   res;
    mp_int   tmp;
    mp_sign  sgn;
    mp_digit rem, rdx = (mp_digit)radix;
    char     ch;

    if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
      return res;

    /* Save sign for later, and take absolute value */
    sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS;

    /* Generate output digits in reverse order      */
    while(mp_cmp_z(&tmp) != 0) {
      if((res = s_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) {
	mp_clear(&tmp);
	return res;
      }

      /* Generate digits, use capital letters */
      ch = s_mp_todigit(rem, radix, 0);

      str[pos++] = ch;
    }

    /* Add - sign if original value was negative */
    if(sgn == MP_NEG)
      str[pos++] = '-';

    /* Add trailing NUL to end the string        */
    str[pos--] = '\0';

    /* Reverse the digits and sign indicator     */
    ix = 0;
    while(ix < pos) {
      char tmp = str[ix];

      str[ix] = str[pos];
      str[pos] = tmp;
      ++ix;
      --pos;
    }
    
    mp_clear(&tmp);
  }

  return MP_OKAY;

} /* end mp_toradix() */

/* }}} */

/* {{{ mp_char2value(ch, r) */

int    mp_char2value(char ch, int r)
{
  return s_mp_tovalue(ch, r);

} /* end mp_tovalue() */

/* }}} */

/* }}} */

/* {{{ mp_strerror(ec) */

/*
  mp_strerror(ec)

  Return a string describing the meaning of error code 'ec'.  The
  string returned is allocated in static memory, so the caller should
  not attempt to modify or free the memory associated with this
  string.
 */
const char  *mp_strerror(mp_err ec)
{
  int   aec = (ec < 0) ? -ec : ec;

  /* Code values are negative, so the senses of these comparisons
     are accurate */
  if(ec < MP_LAST_CODE || ec > MP_OKAY) {
    return mp_err_string[0];  /* unknown error code */
  } else {
    return mp_err_string[aec + 1];
  }

} /* end mp_strerror() */

/* }}} */

/*========================================================================*/
/*------------------------------------------------------------------------*/
/* Static function definitions (internal use only)                        */

/* {{{ Memory management */

/* {{{ s_mp_grow(mp, min) */

/* Make sure there are at least 'min' digits allocated to mp              */
mp_err   s_mp_grow(mp_int *mp, mp_size min)
{
  if(min > ALLOC(mp)) {
    mp_digit   *tmp;

    /* Set min to next nearest default precision block size */
    min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec;

    if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)
      return MP_MEM;

    s_mp_copy(DIGITS(mp), tmp, USED(mp));

#if MP_CRYPTO
    s_mp_setz(DIGITS(mp), ALLOC(mp));
#endif
    s_mp_free(DIGITS(mp));
    DIGITS(mp) = tmp;
    ALLOC(mp) = min;
  }

  return MP_OKAY;

} /* end s_mp_grow() */

/* }}} */

/* {{{ s_mp_pad(mp, min) */

/* Make sure the used size of mp is at least 'min', growing if needed     */
mp_err   s_mp_pad(mp_int *mp, mp_size min)
{
  if(min > USED(mp)) {
    mp_err  res;

    /* Make sure there is room to increase precision  */
    if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY)
      return res;

    /* Increase precision; should already be 0-filled */
    USED(mp) = min;
  }

  return MP_OKAY;

} /* end s_mp_pad() */

/* }}} */

/* {{{ s_mp_setz(dp, count) */

#if MP_MACRO == 0
/* Set 'count' digits pointed to by dp to be zeroes                       */
void s_mp_setz(mp_digit *dp, mp_size count)
{
#if MP_MEMSET == 0
  int  ix;

  for(ix = 0; ix < count; ix++)
    dp[ix] = 0;
#else
  memset(dp, 0, count * sizeof(mp_digit));
#endif

} /* end s_mp_setz() */
#endif

/* }}} */

/* {{{ s_mp_copy(sp, dp, count) */

#if MP_MACRO == 0
/* Copy 'count' digits from sp to dp                                      */
void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count)
{
#if MP_MEMCPY == 0
  int  ix;

  for(ix = 0; ix < count; ix++)
    dp[ix] = sp[ix];
#else
  memcpy(dp, sp, count * sizeof(mp_digit));
#endif

} /* end s_mp_copy() */
#endif

/* }}} */

/* {{{ s_mp_alloc(nb, ni) */

#if MP_MACRO == 0
/* Allocate ni records of nb bytes each, and return a pointer to that     */
void    *s_mp_alloc(size_t nb, size_t ni)
{
  return calloc(nb, ni);

} /* end s_mp_alloc() */
#endif

/* }}} */

/* {{{ s_mp_free(ptr) */

#if MP_MACRO == 0
/* Free the memory pointed to by ptr                                      */
void     s_mp_free(void *ptr)
{
  if(ptr)
    free(ptr);

} /* end s_mp_free() */
#endif

/* }}} */

/* {{{ s_mp_clamp(mp) */

/* Remove leading zeroes from the given value                             */
void     s_mp_clamp(mp_int *mp)
{
  mp_size   du = USED(mp);
  mp_digit *zp = DIGITS(mp) + du - 1;

  while(du > 1 && !*zp--)
    --du;

  USED(mp) = du;

} /* end s_mp_clamp() */


/* }}} */

/* {{{ s_mp_exch(a, b) */

/* Exchange the data for a and b; (b, a) = (a, b)                         */
void     s_mp_exch(mp_int *a, mp_int *b)
{
  mp_int   tmp;

  tmp = *a;
  *a = *b;
  *b = tmp;

} /* end s_mp_exch() */

/* }}} */

/* }}} */

/* {{{ Arithmetic helpers */

/* {{{ s_mp_lshd(mp, p) */

/* 
   Shift mp leftward by p digits, growing if needed, and zero-filling
   the in-shifted digits at the right end.  This is a convenient
   alternative to multiplication by powers of the radix
 */   

mp_err   s_mp_lshd(mp_int *mp, mp_size p)
{
  mp_err   res;
  mp_size  pos;
  mp_digit *dp;
  int     ix;

  if(p == 0)
    return MP_OKAY;

  if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
    return res;

  pos = USED(mp) - 1;
  dp = DIGITS(mp);

  /* Shift all the significant figures over as needed */
  for(ix = pos - p; ix >= 0; ix--) 
    dp[ix + p] = dp[ix];

  /* Fill the bottom digits with zeroes */
  for(ix = 0; ix < p; ix++)
    dp[ix] = 0;

  return MP_OKAY;

} /* end s_mp_lshd() */

/* }}} */

/* {{{ s_mp_rshd(mp, p) */

/* 
   Shift mp rightward by p digits.  Maintains the invariant that
   digits above the precision are all zero.  Digits shifted off the
   end are lost.  Cannot fail.
 */

void     s_mp_rshd(mp_int *mp, mp_size p)
{
  mp_size  ix;
  mp_digit *dp;

  if(p == 0)
    return;

  /* Shortcut when all digits are to be shifted off */
  if(p >= USED(mp)) {
    s_mp_setz(DIGITS(mp), ALLOC(mp));
    USED(mp) = 1;
    SIGN(mp) = MP_ZPOS;
    return;
  }

  /* Shift all the significant figures over as needed */
  dp = DIGITS(mp);
  for(ix = p; ix < USED(mp); ix++)
    dp[ix - p] = dp[ix];

  /* Fill the top digits with zeroes */
  ix -= p;
  while(ix < USED(mp))
    dp[ix++] = 0;

  /* Strip off any leading zeroes    */
  s_mp_clamp(mp);

} /* end s_mp_rshd() */

/* }}} */

/* {{{ s_mp_div_2(mp) */

/* Divide by two -- take advantage of radix properties to do it fast      */
void     s_mp_div_2(mp_int *mp)
{
  s_mp_div_2d(mp, 1);

} /* end s_mp_div_2() */

/* }}} */

/* {{{ s_mp_mul_2(mp) */

mp_err s_mp_mul_2(mp_int *mp)
{
  int      ix;
  mp_digit kin = 0, kout, *dp = DIGITS(mp);
  mp_err   res;

  /* Shift digits leftward by 1 bit */
  for(ix = 0; ix < USED(mp); ix++) {
    kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1;
    dp[ix] = (dp[ix] << 1) | kin;

    kin = kout;
  }

  /* Deal with rollover from last digit */
  if(kin) {
    if(ix >= ALLOC(mp)) {
      if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
	return res;
      dp = DIGITS(mp);
    }

    dp[ix] = kin;
    USED(mp) += 1;
  }

  return MP_OKAY;

} /* end s_mp_mul_2() */

/* }}} */

/* {{{ s_mp_mod_2d(mp, d) */

/*
  Remainder the integer by 2^d, where d is a number of bits.  This
  amounts to a bitwise AND of the value, and does not require the full
  division code
 */
void     s_mp_mod_2d(mp_int *mp, mp_digit d)
{
  unsigned int  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
  unsigned int  ix;
  mp_digit      dmask, *dp = DIGITS(mp);

  if(ndig >= USED(mp))
    return;

  /* Flush all the bits above 2^d in its digit */
  dmask = (1 << nbit) - 1;
  dp[ndig] &= dmask;

  /* Flush all digits above the one with 2^d in it */
  for(ix = ndig + 1; ix < USED(mp); ix++)
    dp[ix] = 0;

  s_mp_clamp(mp);

} /* end s_mp_mod_2d() */

/* }}} */

/* {{{ s_mp_mul_2d(mp, d) */

/*
  Multiply by the integer 2^d, where d is a number of bits.  This
  amounts to a bitwise shift of the value, and does not require the
  full multiplication code.
 */
mp_err    s_mp_mul_2d(mp_int *mp, mp_digit d)
{
  mp_err   res;
  mp_digit save, next, mask, *dp;
  mp_size  used;
  int      ix;

  if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY)
    return res;

  dp = DIGITS(mp); used = USED(mp);
  d %= DIGIT_BIT;

  mask = (1 << d) - 1;

  /* If the shift requires another digit, make sure we've got one to
     work with */
  if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) {
    if((res = s_mp_grow(mp, used + 1)) != MP_OKAY)
      return res;
    dp = DIGITS(mp);
  }

  /* Do the shifting... */
  save = 0;
  for(ix = 0; ix < used; ix++) {
    next = (dp[ix] >> (DIGIT_BIT - d)) & mask;
    dp[ix] = (dp[ix] << d) | save;
    save = next;
  }

  /* If, at this point, we have a nonzero carryout into the next
     digit, we'll increase the size by one digit, and store it...
   */
  if(save) {
    dp[used] = save;
    USED(mp) += 1;
  }

  s_mp_clamp(mp);
  return MP_OKAY;

} /* end s_mp_mul_2d() */

/* }}} */

/* {{{ s_mp_div_2d(mp, d) */

/*
  Divide the integer by 2^d, where d is a number of bits.  This
  amounts to a bitwise shift of the value, and does not require the
  full division code (used in Barrett reduction, see below)
 */
void     s_mp_div_2d(mp_int *mp, mp_digit d)
{
  int       ix;
  mp_digit  save, next, mask, *dp = DIGITS(mp);

  s_mp_rshd(mp, d / DIGIT_BIT);
  d %= DIGIT_BIT;

  mask = (1 << d) - 1;

  save = 0;
  for(ix = USED(mp) - 1; ix >= 0; ix--) {
    next = dp[ix] & mask;
    dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d));
    save = next;
  }

  s_mp_clamp(mp);

} /* end s_mp_div_2d() */

/* }}} */

/* {{{ s_mp_norm(a, b) */

/*
  s_mp_norm(a, b)

  Normalize a and b for division, where b is the divisor.  In order
  that we might make good guesses for quotient digits, we want the
  leading digit of b to be at least half the radix, which we
  accomplish by multiplying a and b by a constant.  This constant is
  returned (so that it can be divided back out of the remainder at the
  end of the division process).

  We multiply by the smallest power of 2 that gives us a leading digit
  at least half the radix.  By choosing a power of 2, we simplify the 
  multiplication and division steps to simple shifts.
 */
mp_digit s_mp_norm(mp_int *a, mp_int *b)
{
  mp_digit  t, d = 0;

  t = DIGIT(b, USED(b) - 1);
  while(t < (RADIX / 2)) {
    t <<= 1;
    ++d;
  }
    
  if(d != 0) {
    s_mp_mul_2d(a, d);
    s_mp_mul_2d(b, d);
  }

  return d;

} /* end s_mp_norm() */

/* }}} */

/* }}} */

/* {{{ Primitive digit arithmetic */

/* {{{ s_mp_add_d(mp, d) */

/* Add d to |mp| in place                                                 */
mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
{
  mp_word   w, k = 0;
  mp_size   ix = 1, used = USED(mp);
  mp_digit *dp = DIGITS(mp);

  w = dp[0] + d;
  dp[0] = ACCUM(w);
  k = CARRYOUT(w);

  while(ix < used && k) {
    w = dp[ix] + k;
    dp[ix] = ACCUM(w);
    k = CARRYOUT(w);
    ++ix;
  }

  if(k != 0) {
    mp_err  res;

    if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
      return res;

    DIGIT(mp, ix) = k;
  }

  return MP_OKAY;

} /* end s_mp_add_d() */

/* }}} */

/* {{{ s_mp_sub_d(mp, d) */

/* Subtract d from |mp| in place, assumes |mp| > d                        */
mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
{
  mp_word   w, b = 0;
  mp_size   ix = 1, used = USED(mp);
  mp_digit *dp = DIGITS(mp);

  /* Compute initial subtraction    */
  w = (RADIX + dp[0]) - d;
  b = CARRYOUT(w) ? 0 : 1;
  dp[0] = ACCUM(w);

  /* Propagate borrows leftward     */
  while(b && ix < used) {
    w = (RADIX + dp[ix]) - b;
    b = CARRYOUT(w) ? 0 : 1;
    dp[ix] = ACCUM(w);
    ++ix;
  }

  /* Remove leading zeroes          */
  s_mp_clamp(mp);

  /* If we have a borrow out, it's a violation of the input invariant */
  if(b)
    return MP_RANGE;
  else
    return MP_OKAY;

} /* end s_mp_sub_d() */

/* }}} */

/* {{{ s_mp_mul_d(a, d) */

/* Compute a = a * d, single digit multiplication                         */
mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
{
  mp_word w, k = 0;
  mp_size ix, max;
  mp_err  res;
  mp_digit *dp = DIGITS(a);

  /*
    Single-digit multiplication will increase the precision of the
    output by at most one digit.  However, we can detect when this
    will happen -- if the high-order digit of a, times d, gives a
    two-digit result, then the precision of the result will increase;
    otherwise it won't.  We use this fact to avoid calling s_mp_pad()
    unless absolutely necessary.
   */
  max = USED(a);
  w = dp[max - 1] * d;
  if(CARRYOUT(w) != 0) {
    if((res = s_mp_pad(a, max + 1)) != MP_OKAY)
      return res;
    dp = DIGITS(a);
  }

  for(ix = 0; ix < max; ix++) {
    w = (dp[ix] * d) + k;
    dp[ix] = ACCUM(w);
    k = CARRYOUT(w);
  }

  /* If there is a precision increase, take care of it here; the above
     test guarantees we have enough storage to do this safely.
   */
  if(k) {
    dp[max] = k; 
    USED(a) = max + 1;
  }

  s_mp_clamp(a);

  return MP_OKAY;
  
} /* end s_mp_mul_d() */

/* }}} */

/* {{{ s_mp_div_d(mp, d, r) */

/*
  s_mp_div_d(mp, d, r)

  Compute the quotient mp = mp / d and remainder r = mp mod d, for a
  single digit d.  If r is null, the remainder will be discarded.
 */

mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
{
  mp_word   w = 0, t;
  mp_int    quot;
  mp_err    res;
  mp_digit *dp = DIGITS(mp), *qp;
  int       ix;

  if(d == 0)
    return MP_RANGE;

  /* Make room for the quotient */
  if((res = mp_init_size(&quot, USED(mp))) != MP_OKAY)
    return res;

  USED(&quot) = USED(mp); /* so clamping will work below */
  qp = DIGITS(&quot);

  /* Divide without subtraction */
  for(ix = USED(mp) - 1; ix >= 0; ix--) {
    w = (w << DIGIT_BIT) | dp[ix];

    if(w >= d) {
      t = w / d;
      w = w % d;
    } else {
      t = 0;
    }

    qp[ix] = t;
  }

  /* Deliver the remainder, if desired */
  if(r)
    *r = w;

  s_mp_clamp(&quot);
  mp_exch(&quot, mp);
  mp_clear(&quot);

  return MP_OKAY;

} /* end s_mp_div_d() */

/* }}} */

/* }}} */

/* {{{ Primitive full arithmetic */

/* {{{ s_mp_add(a, b) */

/* Compute a = |a| + |b|                                                  */
mp_err   s_mp_add(mp_int *a, mp_int *b)        /* magnitude addition      */
{
  mp_word   w = 0;
  mp_digit *pa, *pb;
  mp_size   ix, used = USED(b);
  mp_err    res;

  /* Make sure a has enough precision for the output value */
  if((used > USED(a)) && (res = s_mp_pad(a, used)) != MP_OKAY)
    return res;

  /*
    Add up all digits up to the precision of b.  If b had initially
    the same precision as a, or greater, we took care of it by the
    padding step above, so there is no problem.  If b had initially
    less precision, we'll have to make sure the carry out is duly
    propagated upward among the higher-order digits of the sum.
   */
  pa = DIGITS(a);
  pb = DIGITS(b);
  for(ix = 0; ix < used; ++ix) {
    w += *pa + *pb++;
    *pa++ = ACCUM(w);
    w = CARRYOUT(w);
  }

  /* If we run out of 'b' digits before we're actually done, make
     sure the carries get propagated upward...  
   */
  used = USED(a);
  while(w && ix < used) {
    w += *pa;
    *pa++ = ACCUM(w);
    w = CARRYOUT(w);
    ++ix;
  }

  /* If there's an overall carry out, increase precision and include
     it.  We could have done this initially, but why touch the memory
     allocator unless we're sure we have to?
   */
  if(w) {
    if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
      return res;

    DIGIT(a, ix) = w;  /* pa may not be valid after s_mp_pad() call */
  }

  return MP_OKAY;

} /* end s_mp_add() */

/* }}} */

/* {{{ s_mp_sub(a, b) */

/* Compute a = |a| - |b|, assumes |a| >= |b|                              */
mp_err   s_mp_sub(mp_int *a, mp_int *b)        /* magnitude subtract      */
{
  mp_word   w = 0;
  mp_digit *pa, *pb;
  mp_size   ix, used = USED(b);

  /*
    Subtract and propagate borrow.  Up to the precision of b, this
    accounts for the digits of b; after that, we just make sure the
    carries get to the right place.  This saves having to pad b out to
    the precision of a just to make the loops work right...
   */
  pa = DIGITS(a);
  pb = DIGITS(b);

  for(ix = 0; ix < used; ++ix) {
    w = (RADIX + *pa) - w - *pb++;
    *pa++ = ACCUM(w);
    w = CARRYOUT(w) ? 0 : 1;
  }

  used = USED(a);
  while(ix < used) {
    w = RADIX + *pa - w;
    *pa++ = ACCUM(w);
    w = CARRYOUT(w) ? 0 : 1;
    ++ix;
  }

  /* Clobber any leading zeroes we created    */
  s_mp_clamp(a);

  /* 
     If there was a borrow out, then |b| > |a| in violation
     of our input invariant.  We've already done the work,
     but we'll at least complain about it...
   */
  if(w)
    return MP_RANGE;
  else
    return MP_OKAY;

} /* end s_mp_sub() */

/* }}} */

mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
{
  mp_int   q;
  mp_err   res;
  mp_size  um = USED(m);

  if((res = mp_init_copy(&q, x)) != MP_OKAY)
    return res;

  s_mp_rshd(&q, um - 1);       /* q1 = x / b^(k-1)  */
  s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
  s_mp_rshd(&q, um + 1);       /* q3 = q2 / b^(k+1) */

  /* x = x mod b^(k+1), quick (no division) */
  s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));

  /* q = q * m mod b^(k+1), quick (no division), uses the short multiplier */
#ifndef SHRT_MUL
  s_mp_mul(&q, m);
  s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
#else
  s_mp_mul_dig(&q, m, um + 1);
#endif  

  /* x = x - q */
  if((res = mp_sub(x, &q, x)) != MP_OKAY)
    goto CLEANUP;

  /* If x < 0, add b^(k+1) to it */
  if(mp_cmp_z(x) < 0) {
    mp_set(&q, 1);
    if((res = s_mp_lshd(&q, um + 1)) != MP_OKAY)
      goto CLEANUP;
    if((res = mp_add(x, &q, x)) != MP_OKAY)
      goto CLEANUP;
  }

  /* Back off if it's too big */
  while(mp_cmp(x, m) >= 0) {
    if((res = s_mp_sub(x, m)) != MP_OKAY)
      break;
  }

 CLEANUP:
  mp_clear(&q);

  return res;

} /* end s_mp_reduce() */



/* {{{ s_mp_mul(a, b) */

/* Compute a = |a| * |b|                                                  */
mp_err   s_mp_mul(mp_int *a, mp_int *b)
{
  mp_word   w, k = 0;
  mp_int    tmp;
  mp_err    res;
  mp_size   ix, jx, ua = USED(a), ub = USED(b);
  mp_digit *pa, *pb, *pt, *pbt;

  if((res = mp_init_size(&tmp, ua + ub)) != MP_OKAY)
    return res;

  /* This has the effect of left-padding with zeroes... */
  USED(&tmp) = ua + ub;

  /* We're going to need the base value each iteration */
  pbt = DIGITS(&tmp);

  /* Outer loop:  Digits of b */

  pb = DIGITS(b);
  for(ix = 0; ix < ub; ++ix, ++pb) {
    if(*pb == 0) 
      continue;

    /* Inner product:  Digits of a */
    pa = DIGITS(a);
    for(jx = 0; jx < ua; ++jx, ++pa) {
      pt = pbt + ix + jx;
      w = *pb * *pa + k + *pt;
      *pt = ACCUM(w);
      k = CARRYOUT(w);
    }

    pbt[ix + jx] = k;
    k = 0;
  }

  s_mp_clamp(&tmp);
  s_mp_exch(&tmp, a);

  mp_clear(&tmp);

  return MP_OKAY;

} /* end s_mp_mul() */

/* }}} */

/* {{{ s_mp_kmul(a, b, out, len) */

#if 0
void   s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len)
{
  mp_word   w, k = 0;
  mp_size   ix, jx;
  mp_digit *pa, *pt;

  for(ix = 0; ix < len; ++ix, ++b) {
    if(*b == 0)
      continue;
    
    pa = a;
    for(jx = 0; jx < len; ++jx, ++pa) {
      pt = out + ix + jx;
      w = *b * *pa + k + *pt;
      *pt = ACCUM(w);
      k = CARRYOUT(w);
    }

    out[ix + jx] = k;
    k = 0;
  }

} /* end s_mp_kmul() */
#endif

/* }}} */

/* {{{ s_mp_sqr(a) */

/*
  Computes the square of a, in place.  This can be done more
  efficiently than a general multiplication, because many of the
  computation steps are redundant when squaring.  The inner product
  step is a bit more complicated, but we save a fair number of
  iterations of the multiplication loop.
 */
#if MP_SQUARE
mp_err   s_mp_sqr(mp_int *a)
{
  mp_word  w, k = 0;
  mp_int   tmp;
  mp_err   res;
  mp_size  ix, jx, kx, used = USED(a);
  mp_digit *pa1, *pa2, *pt, *pbt;

  if((res = mp_init_size(&tmp, 2 * used)) != MP_OKAY)
    return res;

  /* Left-pad with zeroes */
  USED(&tmp) = 2 * used;

  /* We need the base value each time through the loop */
  pbt = DIGITS(&tmp);

  pa1 = DIGITS(a);
  for(ix = 0; ix < used; ++ix, ++pa1) {
    if(*pa1 == 0)
      continue;

    w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1);

    pbt[ix + ix] = ACCUM(w);
    k = CARRYOUT(w);

    /*
      The inner product is computed as:

         (C, S) = t[i,j] + 2 a[i] a[j] + C

      This can overflow what can be represented in an mp_word, and
      since C arithmetic does not provide any way to check for
      overflow, we have to check explicitly for overflow conditions
      before they happen.
     */
    for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) {
      mp_word  u = 0, v;
      
      /* Store this in a temporary to avoid indirections later */
      pt = pbt + ix + jx;

      /* Compute the multiplicative step */
      w = *pa1 * *pa2;

      /* If w is more than half MP_WORD_MAX, the doubling will
	 overflow, and we need to record a carry out into the next
	 word */
      u = (w >> (MP_WORD_BIT - 1)) & 1;

      /* Double what we've got, overflow will be ignored as defined
	 for C arithmetic (we've already noted if it is to occur)
       */
      w *= 2;

      /* Compute the additive step */
      v = *pt + k;

      /* If we do not already have an overflow carry, check to see
	 if the addition will cause one, and set the carry out if so 
       */
      u |= ((MP_WORD_MAX - v) < w);

      /* Add in the rest, again ignoring overflow */
      w += v;

      /* Set the i,j digit of the output */
      *pt = ACCUM(w);

      /* Save carry information for the next iteration of the loop.
	 This is why k must be an mp_word, instead of an mp_digit */
      k = CARRYOUT(w) | (u << DIGIT_BIT);

    } /* for(jx ...) */

    /* Set the last digit in the cycle and reset the carry */
    k = DIGIT(&tmp, ix + jx) + k;
    pbt[ix + jx] = ACCUM(k);
    k = CARRYOUT(k);

    /* If we are carrying out, propagate the carry to the next digit
       in the output.  This may cascade, so we have to be somewhat
       circumspect -- but we will have enough precision in the output
       that we won't overflow 
     */
    kx = 1;
    while(k) {
      k = pbt[ix + jx + kx] + 1;
      pbt[ix + jx + kx] = ACCUM(k);
      k = CARRYOUT(k);
      ++kx;
    }
  } /* for(ix ...) */

  s_mp_clamp(&tmp);
  s_mp_exch(&tmp, a);

  mp_clear(&tmp);

  return MP_OKAY;

} /* end s_mp_sqr() */
#endif

/* }}} */

/* {{{ s_mp_div(a, b) */

/*
  s_mp_div(a, b)

  Compute a = a / b and b = a mod b.  Assumes b > a.
 */

mp_err   s_mp_div(mp_int *a, mp_int *b)
{
  mp_int   quot, rem, t;
  mp_word  q;
  mp_err   res;
  mp_digit d;
  int      ix;

  if(mp_cmp_z(b) == 0)
    return MP_RANGE;

  /* Shortcut if b is power of two */
  if((ix = s_mp_ispow2(b)) >= 0) {
    mp_copy(a, b);  /* need this for remainder */
    s_mp_div_2d(a, (mp_digit)ix);
    s_mp_mod_2d(b, (mp_digit)ix);

    return MP_OKAY;
  }

  /* Allocate space to store the quotient */
  if((res = mp_init_size(&quot, USED(a))) != MP_OKAY)
    return res;

  /* A working temporary for division     */
  if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
    goto T;

  /* Allocate space for the remainder     */
  if((res = mp_init_size(&rem, USED(a))) != MP_OKAY)
    goto REM;

  /* Normalize to optimize guessing       */
  d = s_mp_norm(a, b);

  /* Perform the division itself...woo!   */
  ix = USED(a) - 1;

  while(ix >= 0) {
    /* Find a partial substring of a which is at least b */
    while(s_mp_cmp(&rem, b) < 0 && ix >= 0) {
      if((res = s_mp_lshd(&rem, 1)) != MP_OKAY) 
	goto CLEANUP;

      if((res = s_mp_lshd(&quot, 1)) != MP_OKAY)
	goto CLEANUP;

      DIGIT(&rem, 0) = DIGIT(a, ix);
      s_mp_clamp(&rem);
      --ix;
    }

    /* If we didn't find one, we're finished dividing    */
    if(s_mp_cmp(&rem, b) < 0) 
      break;    

    /* Compute a guess for the next quotient digit       */
    q = DIGIT(&rem, USED(&rem) - 1);
    if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1)
      q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2);

    q /= DIGIT(b, USED(b) - 1);

    /* The guess can be as much as RADIX + 1 */
    if(q >= RADIX)
      q = RADIX - 1;

    /* See what that multiplies out to                   */
    mp_copy(b, &t);
    if((res = s_mp_mul_d(&t, q)) != MP_OKAY)
      goto CLEANUP;

    /* 
       If it's too big, back it off.  We should not have to do this
       more than once, or, in rare cases, twice.  Knuth describes a
       method by which this could be reduced to a maximum of once, but
       I didn't implement that here.
     */
    while(s_mp_cmp(&t, &rem) > 0) {
      --q;
      s_mp_sub(&t, b);
    }

    /* At this point, q should be the right next digit   */
    if((res = s_mp_sub(&rem, &t)) != MP_OKAY)
      goto CLEANUP;

    /*
      Include the digit in the quotient.  We allocated enough memory
      for any quotient we could ever possibly get, so we should not
      have to check for failures here
     */
    DIGIT(&quot, 0) = q;
  }

  /* Denormalize remainder                */
  if(d != 0) 
    s_mp_div_2d(&rem, d);

  s_mp_clamp(&quot);
  s_mp_clamp(&rem);

  /* Copy quotient back to output         */
  s_mp_exch(&quot, a);
  
  /* Copy remainder back to output        */
  s_mp_exch(&rem, b);

CLEANUP:
  mp_clear(&rem);
REM:
  mp_clear(&t);
T:
  mp_clear(&quot);

  return res;

} /* end s_mp_div() */

/* }}} */

/* {{{ s_mp_2expt(a, k) */

mp_err   s_mp_2expt(mp_int *a, mp_digit k)
{
  mp_err    res;
  mp_size   dig, bit;

  dig = k / DIGIT_BIT;
  bit = k % DIGIT_BIT;

  mp_zero(a);
  if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
    return res;
  
  DIGIT(a, dig) |= (1 << bit);

  return MP_OKAY;

} /* end s_mp_2expt() */

/* }}} */


/* }}} */

/* }}} */

/* {{{ Primitive comparisons */

/* {{{ s_mp_cmp(a, b) */

/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
int      s_mp_cmp(mp_int *a, mp_int *b)
{
  mp_size   ua = USED(a), ub = USED(b);

  if(ua > ub)
    return MP_GT;
  else if(ua < ub)
    return MP_LT;
  else {
    int      ix = ua - 1;
    mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix;

    while(ix >= 0) {
      if(*ap > *bp)
	return MP_GT;
      else if(*ap < *bp)
	return MP_LT;

      --ap; --bp; --ix;
    }

    return MP_EQ;
  }

} /* end s_mp_cmp() */

/* }}} */

/* {{{ s_mp_cmp_d(a, d) */

/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
int      s_mp_cmp_d(mp_int *a, mp_digit d)
{
  mp_size  ua = USED(a);
  mp_digit *ap = DIGITS(a);

  if(ua > 1)
    return MP_GT;

  if(*ap < d) 
    return MP_LT;
  else if(*ap > d)
    return MP_GT;
  else
    return MP_EQ;

} /* end s_mp_cmp_d() */

/* }}} */

/* {{{ s_mp_ispow2(v) */

/*
  Returns -1 if the value is not a power of two; otherwise, it returns
  k such that v = 2^k, i.e. lg(v).
 */
int      s_mp_ispow2(mp_int *v)
{
  mp_digit d, *dp;
  mp_size  uv = USED(v);
  int      extra = 0, ix;

  d = DIGIT(v, uv - 1); /* most significant digit of v */

  while(d && ((d & 1) == 0)) {
    d >>= 1;
    ++extra;
  }

  if(d == 1) {
    ix = uv - 2;
    dp = DIGITS(v) + ix;

    while(ix >= 0) {
      if(*dp)
	return -1; /* not a power of two */

      --dp; --ix;
    }

    return ((uv - 1) * DIGIT_BIT) + extra;
  } 

  return -1;

} /* end s_mp_ispow2() */

/* }}} */

/* {{{ s_mp_ispow2d(d) */

int      s_mp_ispow2d(mp_digit d)
{
  int   pow = 0;

  while((d & 1) == 0) {
    ++pow; d >>= 1;
  }

  if(d == 1)
    return pow;

  return -1;

} /* end s_mp_ispow2d() */

/* }}} */

/* }}} */

/* {{{ Primitive I/O helpers */

/* {{{ s_mp_tovalue(ch, r) */

/*
  Convert the given character to its digit value, in the given radix.
  If the given character is not understood in the given radix, -1 is
  returned.  Otherwise the digit's numeric value is returned.

  The results will be odd if you use a radix < 2 or > 62, you are
  expected to know what you're up to.
 */
int      s_mp_tovalue(char ch, int r)
{
  int    val, xch;
  
  if(r > 36)
    xch = ch;
  else
    xch = toupper(ch);

  if(isdigit(xch))
    val = xch - '0';
  else if(isupper(xch))
    val = xch - 'A' + 10;
  else if(islower(xch))
    val = xch - 'a' + 36;
  else if(xch == '+')
    val = 62;
  else if(xch == '/')
    val = 63;
  else 
    return -1;

  if(val < 0 || val >= r)
    return -1;

  return val;

} /* end s_mp_tovalue() */

/* }}} */

/* {{{ s_mp_todigit(val, r, low) */

/*
  Convert val to a radix-r digit, if possible.  If val is out of range
  for r, returns zero.  Otherwise, returns an ASCII character denoting
  the value in the given radix.

  The results may be odd if you use a radix < 2 or > 64, you are
  expected to know what you're doing.
 */
  
char     s_mp_todigit(int val, int r, int low)
{
  char   ch;

  if(val < 0 || val >= r)
    return 0;

  ch = s_dmap_1[val];

  if(r <= 36 && low)
    ch = tolower(ch);

  return ch;

} /* end s_mp_todigit() */

/* }}} */

/* {{{ s_mp_outlen(bits, radix) */

/* 
   Return an estimate for how long a string is needed to hold a radix
   r representation of a number with 'bits' significant bits.

   Does not include space for a sign or a NUL terminator.
 */
int      s_mp_outlen(int bits, int r)
{
  return (int)((double)bits * LOG_V_2(r));

} /* end s_mp_outlen() */

/* }}} */

/* }}} */

/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS                                                  */
/* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */

Added libtommath/mtest/mpi.h.



































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
    mpi.h

    by Michael J. Fromberger <[email protected]>
    Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved

    Arbitrary precision integer arithmetic library
 */

#ifndef _H_MPI_
#define _H_MPI_

#include "mpi-config.h"

#define  MP_LT       -1
#define  MP_EQ        0
#define  MP_GT        1

#if MP_DEBUG
#undef MP_IOFUNC
#define MP_IOFUNC 1
#endif

#if MP_IOFUNC
#include <stdio.h>
#include <ctype.h>
#endif

#include <limits.h>

#define  MP_NEG  1
#define  MP_ZPOS 0

/* Included for compatibility... */
#define  NEG     MP_NEG
#define  ZPOS    MP_ZPOS

#define  MP_OKAY          0 /* no error, all is well */
#define  MP_YES           0 /* yes (boolean result)  */
#define  MP_NO           -1 /* no (boolean result)   */
#define  MP_MEM          -2 /* out of memory         */
#define  MP_RANGE        -3 /* argument out of range */
#define  MP_BADARG       -4 /* invalid parameter     */
#define  MP_UNDEF        -5 /* answer is undefined   */
#define  MP_LAST_CODE    MP_UNDEF

#include "mpi-types.h"

/* Included for compatibility... */
#define DIGIT_BIT         MP_DIGIT_BIT
#define DIGIT_MAX         MP_DIGIT_MAX

/* Macros for accessing the mp_int internals           */
#define  SIGN(MP)     ((MP)->sign)
#define  USED(MP)     ((MP)->used)
#define  ALLOC(MP)    ((MP)->alloc)
#define  DIGITS(MP)   ((MP)->dp)
#define  DIGIT(MP,N)  (MP)->dp[(N)]

#if MP_ARGCHK == 1
#define  ARGCHK(X,Y)  {if(!(X)){return (Y);}}
#elif MP_ARGCHK == 2
#include <assert.h>
#define  ARGCHK(X,Y)  assert(X)
#else
#define  ARGCHK(X,Y)  /*  */
#endif

/* This defines the maximum I/O base (minimum is 2)   */
#define MAX_RADIX         64

typedef struct {
  mp_sign       sign;    /* sign of this quantity      */
  mp_size       alloc;   /* how many digits allocated  */
  mp_size       used;    /* how many digits used       */
  mp_digit     *dp;      /* the digits themselves      */
} mp_int;

/*------------------------------------------------------------------------*/
/* Default precision                                                      */

unsigned int mp_get_prec(void);
void         mp_set_prec(unsigned int prec);

/*------------------------------------------------------------------------*/
/* Memory management                                                      */

mp_err mp_init(mp_int *mp);
mp_err mp_init_array(mp_int mp[], int count);
mp_err mp_init_size(mp_int *mp, mp_size prec);
mp_err mp_init_copy(mp_int *mp, mp_int *from);
mp_err mp_copy(mp_int *from, mp_int *to);
void   mp_exch(mp_int *mp1, mp_int *mp2);
void   mp_clear(mp_int *mp);
void   mp_clear_array(mp_int mp[], int count);
void   mp_zero(mp_int *mp);
void   mp_set(mp_int *mp, mp_digit d);
mp_err mp_set_int(mp_int *mp, long z);
mp_err mp_shrink(mp_int *a);


/*------------------------------------------------------------------------*/
/* Single digit arithmetic                                                */

mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_2(mp_int *a, mp_int *c);
mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
mp_err mp_div_2(mp_int *a, mp_int *c);
mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c);

/*------------------------------------------------------------------------*/
/* Sign manipulations                                                     */

mp_err mp_abs(mp_int *a, mp_int *b);
mp_err mp_neg(mp_int *a, mp_int *b);

/*------------------------------------------------------------------------*/
/* Full arithmetic                                                        */

mp_err mp_add(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c);
#if MP_SQUARE
mp_err mp_sqr(mp_int *a, mp_int *b);
#else
#define mp_sqr(a, b) mp_mul(a, a, b)
#endif
mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r);
mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r);
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_2expt(mp_int *a, mp_digit k);
mp_err mp_sqrt(mp_int *a, mp_int *b);

/*------------------------------------------------------------------------*/
/* Modular arithmetic                                                     */

#if MP_MODARITH
mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c);
mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c);
mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
#if MP_SQUARE
mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
#else
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
#endif
mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
#endif /* MP_MODARITH */

/*------------------------------------------------------------------------*/
/* Comparisons                                                            */

int    mp_cmp_z(mp_int *a);
int    mp_cmp_d(mp_int *a, mp_digit d);
int    mp_cmp(mp_int *a, mp_int *b);
int    mp_cmp_mag(mp_int *a, mp_int *b);
int    mp_cmp_int(mp_int *a, long z);
int    mp_isodd(mp_int *a);
int    mp_iseven(mp_int *a);

/*------------------------------------------------------------------------*/
/* Number theoretic                                                       */

#if MP_NUMTH
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y);
mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c);
#endif /* end MP_NUMTH */

/*------------------------------------------------------------------------*/
/* Input and output                                                       */

#if MP_IOFUNC
void   mp_print(mp_int *mp, FILE *ofp);
#endif /* end MP_IOFUNC */

/*------------------------------------------------------------------------*/
/* Base conversion                                                        */

#define BITS     1
#define BYTES    CHAR_BIT

mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len);
int    mp_signed_bin_size(mp_int *mp);
mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str);

mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len);
int    mp_unsigned_bin_size(mp_int *mp);
mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str);

int    mp_count_bits(mp_int *mp);

#if MP_COMPAT_MACROS
#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
#endif

mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix);
int    mp_radix_size(mp_int *mp, int radix);
int    mp_value_radix_size(int num, int qty, int radix);
mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix);

int    mp_char2value(char ch, int r);

#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S)     mp_toradix((M), (S), 16)

/*------------------------------------------------------------------------*/
/* Error strings                                                          */

const  char  *mp_strerror(mp_err ec);

#endif /* end _H_MPI_ */

Added libtommath/mtest/mtest.c.

































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/* makes a bignum test harness with NUM tests per operation
 *
 * the output is made in the following format [one parameter per line]

operation
operand1
operand2
[... operandN]
result1
result2
[... resultN]

So for example "a * b mod n" would be

mulmod
a
b
n
a*b mod n

e.g. if a=3, b=4 n=11 then

mulmod
3
4
11
1

 */

#ifdef MP_8BIT
#define THE_MASK 127
#else
#define THE_MASK 32767
#endif

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.c"

FILE *rng;

void rand_num(mp_int *a)
{
   int n, size;
   unsigned char buf[2048];

   size = 1 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
   buf[0] = (fgetc(rng)&1)?1:0;
   fread(buf+1, 1, size, rng);
   while (buf[1] == 0) buf[1] = fgetc(rng);
   mp_read_raw(a, buf, 1+size);
}

void rand_num2(mp_int *a)
{
   int n, size;
   unsigned char buf[2048];

   size = 10 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
   buf[0] = (fgetc(rng)&1)?1:0;
   fread(buf+1, 1, size, rng);
   while (buf[1] == 0) buf[1] = fgetc(rng);
   mp_read_raw(a, buf, 1+size);
}

#define mp_to64(a, b) mp_toradix(a, b, 64)

int main(void)
{
   int n, tmp;
   mp_int a, b, c, d, e;
   clock_t t1;
   char buf[4096];

   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);


   /* initial (2^n - 1)^2 testing, makes sure the comba multiplier works [it has the new carry code] */
/*
   mp_set(&a, 1);
   for (n = 1; n < 8192; n++) {
       mp_mul(&a, &a, &c);
       printf("mul\n");
       mp_to64(&a, buf);
       printf("%s\n%s\n", buf, buf);
       mp_to64(&c, buf);
       printf("%s\n", buf);

       mp_add_d(&a, 1, &a);
       mp_mul_2(&a, &a);
       mp_sub_d(&a, 1, &a);
   }
*/

   rng = fopen("/dev/urandom", "rb");
   if (rng == NULL) {
      rng = fopen("/dev/random", "rb");
      if (rng == NULL) {
         fprintf(stderr, "\nWarning:  stdin used as random source\n\n");
         rng = stdin;
      }
   }

   t1 = clock();
   for (;;) {
#if 0
      if (clock() - t1 > CLOCKS_PER_SEC) {
         sleep(2);
         t1 = clock();
      }
#endif
       n = fgetc(rng) % 15;

   if (n == 0) {
       /* add tests */
       rand_num(&a);
       rand_num(&b);
       mp_add(&a, &b, &c);
       printf("add\n");
       mp_to64(&a, buf);
       printf("%s\n", buf);
       mp_to64(&b, buf);
       printf("%s\n", buf);
       mp_to64(&c, buf);
       printf("%s\n", buf);
   } else if (n == 1) {
      /* sub tests */
       rand_num(&a);
       rand_num(&b);
       mp_sub(&a, &b, &c);
       printf("sub\n");
       mp_to64(&a, buf);
       printf("%s\n", buf);
       mp_to64(&b, buf);
       printf("%s\n", buf);
       mp_to64(&c, buf);
       printf("%s\n", buf);
   } else if (n == 2) {
       /* mul tests */
       rand_num(&a);
       rand_num(&b);
       mp_mul(&a, &b, &c);
       printf("mul\n");
       mp_to64(&a, buf);
       printf("%s\n", buf);
       mp_to64(&b, buf);
       printf("%s\n", buf);
       mp_to64(&c, buf);
       printf("%s\n", buf);
   } else if (n == 3) {
      /* div tests */
       rand_num(&a);
       rand_num(&b);
       mp_div(&a, &b, &c, &d);
       printf("div\n");
       mp_to64(&a, buf);
       printf("%s\n", buf);
       mp_to64(&b, buf);
       printf("%s\n", buf);
       mp_to64(&c, buf);
       printf("%s\n", buf);
       mp_to64(&d, buf);
       printf("%s\n", buf);
   } else if (n == 4) {
      /* sqr tests */
       rand_num(&a);
       mp_sqr(&a, &b);
       printf("sqr\n");
       mp_to64(&a, buf);
       printf("%s\n", buf);
       mp_to64(&b, buf);
       printf("%s\n", buf);
   } else if (n == 5) {
      /* mul_2d test */
      rand_num(&a);
      mp_copy(&a, &b);
      n = fgetc(rng) & 63;
      mp_mul_2d(&b, n, &b);
      mp_to64(&a, buf);
      printf("mul2d\n");
      printf("%s\n", buf);
      printf("%d\n", n);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   } else if (n == 6) {
      /* div_2d test */
      rand_num(&a);
      mp_copy(&a, &b);
      n = fgetc(rng) & 63;
      mp_div_2d(&b, n, &b, NULL);
      mp_to64(&a, buf);
      printf("div2d\n");
      printf("%s\n", buf);
      printf("%d\n", n);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   } else if (n == 7) {
      /* gcd test */
      rand_num(&a);
      rand_num(&b);
      a.sign = MP_ZPOS;
      b.sign = MP_ZPOS;
      mp_gcd(&a, &b, &c);
      printf("gcd\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
      mp_to64(&c, buf);
      printf("%s\n", buf);
   } else if (n == 8) {
      /* lcm test */
      rand_num(&a);
      rand_num(&b);
      a.sign = MP_ZPOS;
      b.sign = MP_ZPOS;
      mp_lcm(&a, &b, &c);
      printf("lcm\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
      mp_to64(&c, buf);
      printf("%s\n", buf);
   } else if (n == 9) {
      /* exptmod test */
      rand_num2(&a);
      rand_num2(&b);
      rand_num2(&c);
//      if (c.dp[0]&1) mp_add_d(&c, 1, &c);
      a.sign = b.sign = c.sign = 0;
      mp_exptmod(&a, &b, &c, &d);
      printf("expt\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
      mp_to64(&c, buf);
      printf("%s\n", buf);
      mp_to64(&d, buf);
      printf("%s\n", buf);
   } else if (n == 10) {
      /* invmod test */
      rand_num2(&a);
      rand_num2(&b);
      b.sign = MP_ZPOS;
      a.sign = MP_ZPOS;
      mp_gcd(&a, &b, &c);
      if (mp_cmp_d(&c, 1) != 0) continue;
      if (mp_cmp_d(&b, 1) == 0) continue;
      mp_invmod(&a, &b, &c);
      printf("invmod\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
      mp_to64(&c, buf);
      printf("%s\n", buf);
   } else if (n == 11) {
      rand_num(&a);
      mp_mul_2(&a, &a);
      mp_div_2(&a, &b);
      printf("div2\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   } else if (n == 12) {
      rand_num2(&a);
      mp_mul_2(&a, &b);
      printf("mul2\n");
      mp_to64(&a, buf);
      printf("%s\n", buf);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   } else if (n == 13) {
      rand_num2(&a);
      tmp = abs(rand()) & THE_MASK;
      mp_add_d(&a, tmp, &b);
      printf("add_d\n");
      mp_to64(&a, buf);
      printf("%s\n%d\n", buf, tmp);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   } else if (n == 14) {
      rand_num2(&a);
      tmp = abs(rand()) & THE_MASK;
      mp_sub_d(&a, tmp, &b);
      printf("sub_d\n");
      mp_to64(&a, buf);
      printf("%s\n%d\n", buf, tmp);
      mp_to64(&b, buf);
      printf("%s\n", buf);
   }
   }
   fclose(rng);
   return 0;
}

Added libtommath/pics/design_process.sxd.

cannot compute difference between binary files

Added libtommath/pics/design_process.tif.

cannot compute difference between binary files

Added libtommath/pics/expt_state.sxd.

cannot compute difference between binary files

Added libtommath/pics/expt_state.tif.

cannot compute difference between binary files

Added libtommath/pics/makefile.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# makes the images... yeah

default:  pses

design_process.ps: design_process.tif
	tiff2ps -s -e design_process.tif > design_process.ps

sliding_window.ps: sliding_window.tif
	tiff2ps -s -e sliding_window.tif > sliding_window.ps
	
expt_state.ps: expt_state.tif
	tiff2ps -s -e expt_state.tif > expt_state.ps

primality.ps: primality.tif
	tiff2ps -s -e primality.tif > primality.ps

design_process.pdf: design_process.ps
	epstopdf design_process.ps

sliding_window.pdf: sliding_window.ps
	epstopdf sliding_window.ps
	
expt_state.pdf: expt_state.ps
	epstopdf expt_state.ps

primality.pdf: primality.ps
	epstopdf primality.ps


pses: sliding_window.ps expt_state.ps primality.ps design_process.ps
pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf

clean:
	rm -rf *.ps *.pdf .xvpics
   

Added libtommath/pics/primality.tif.

cannot compute difference between binary files

Added libtommath/pics/radix.sxd.

cannot compute difference between binary files

Added libtommath/pics/sliding_window.sxd.

cannot compute difference between binary files

Added libtommath/pics/sliding_window.tif.

cannot compute difference between binary files

Added libtommath/poster.out.

Added libtommath/poster.pdf.

cannot compute difference between binary files

Added libtommath/poster.tex.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
\documentclass[landscape,11pt]{article}
\usepackage{amsmath, amssymb}
\usepackage{hyperref}
\begin{document}
\hspace*{-3in}
\begin{tabular}{llllll}
$c = a + b$  & {\tt mp\_add(\&a, \&b, \&c)} & $b = 2a$  & {\tt mp\_mul\_2(\&a, \&b)} & \\
$c = a - b$  & {\tt mp\_sub(\&a, \&b, \&c)} & $b = a/2$ & {\tt mp\_div\_2(\&a, \&b)} & \\
$c = ab $   & {\tt mp\_mul(\&a, \&b, \&c)}  & $c = 2^ba$  & {\tt mp\_mul\_2d(\&a, b, \&c)}  \\
$b = a^2 $  & {\tt mp\_sqr(\&a, \&b)}       & $c = a/2^b, d = a \mod 2^b$ & {\tt mp\_div\_2d(\&a, b, \&c, \&d)} \\
$c = \lfloor a/b \rfloor, d = a \mod b$ & {\tt mp\_div(\&a, \&b, \&c, \&d)} & $c = a \mod 2^b $  & {\tt mp\_mod\_2d(\&a, b, \&c)}  \\
 && \\
$a = b $  & {\tt mp\_set\_int(\&a, b)}  & $c = a \vee b$  & {\tt mp\_or(\&a, \&b, \&c)}  \\
$b = a $  & {\tt mp\_copy(\&a, \&b)} & $c = a \wedge b$  & {\tt mp\_and(\&a, \&b, \&c)}  \\
 && $c = a \oplus b$  & {\tt mp\_xor(\&a, \&b, \&c)}  \\
 & \\
$b = -a $  & {\tt mp\_neg(\&a, \&b)}  & $d = a + b \mod c$  & {\tt mp\_addmod(\&a, \&b, \&c, \&d)}  \\
$b = |a| $  & {\tt mp\_abs(\&a, \&b)} & $d = a - b \mod c$  & {\tt mp\_submod(\&a, \&b, \&c, \&d)}  \\
 && $d = ab \mod c$  & {\tt mp\_mulmod(\&a, \&b, \&c, \&d)}  \\
Compare $a$ and $b$ & {\tt mp\_cmp(\&a, \&b)} & $c = a^2 \mod b$  & {\tt mp\_sqrmod(\&a, \&b, \&c)}  \\
Is Zero? & {\tt mp\_iszero(\&a)} & $c = a^{-1} \mod b$  & {\tt mp\_invmod(\&a, \&b, \&c)} \\
Is Even? & {\tt mp\_iseven(\&a)} & $d = a^b \mod c$ & {\tt mp\_exptmod(\&a, \&b, \&c, \&d)} \\
Is Odd ? & {\tt mp\_isodd(\&a)} \\
&\\
$\vert \vert a \vert \vert$ & {\tt mp\_unsigned\_bin\_size(\&a)} & $res$ = 1 if $a$ prime to $t$ rounds? & {\tt mp\_prime\_is\_prime(\&a, t, \&res)} \\
$buf \leftarrow a$          & {\tt mp\_to\_unsigned\_bin(\&a, buf)} & Next prime after $a$ to $t$ rounds. & {\tt mp\_prime\_next\_prime(\&a, t, bbs\_style)} \\
$a \leftarrow buf[0..len-1]$          & {\tt mp\_read\_unsigned\_bin(\&a, buf, len)} \\
&\\
$b = \sqrt{a}$ & {\tt mp\_sqrt(\&a, \&b)}  & $c = \mbox{gcd}(a, b)$ & {\tt mp\_gcd(\&a, \&b, \&c)} \\
$c = a^{1/b}$ & {\tt mp\_n\_root(\&a, b, \&c)} & $c = \mbox{lcm}(a, b)$ & {\tt mp\_lcm(\&a, \&b, \&c)} \\
&\\
Greater Than & MP\_GT & Equal To & MP\_EQ \\
Less Than & MP\_LT & Bits per digit & DIGIT\_BIT \\
\end{tabular}
\end{document}

Added libtommath/pre_gen/mpi.c.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
/* Start: bn_error.c */
#include <tommath.h>
#ifdef BN_ERROR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

static const struct {
     int code;
     char *msg;
} msgs[] = {
     { MP_OKAY, "Successful" },
     { MP_MEM,  "Out of heap" },
     { MP_VAL,  "Value out of range" }
};

/* return a char * string for a given code */
char *mp_error_to_string(int code)
{
   int x;

   /* scan the lookup table for the given message */
   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
       if (msgs[x].code == code) {
          return msgs[x].msg;
       }
   }

   /* generic reply for invalid code */
   return "Invalid error code";
}

#endif

/* End: bn_error.c */

/* Start: bn_fast_mp_invmod.c */
#include <tommath.h>
#ifdef BN_FAST_MP_INVMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes the modular inverse via binary extended euclidean algorithm, 
 * that is c = 1/a mod b 
 *
 * Based on slow invmod except this is optimized for the case where b is 
 * odd as per HAC Note 14.64 on pp. 610
 */
int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, B, D;
  int     res, neg;

  /* 2. [modified] b must be odd   */
  if (mp_iseven (b) == 1) {
    return MP_VAL;
  }

  /* init all our temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x == modulus, y == value to invert */
  if ((res = mp_copy (b, &x)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* we need y = |a| */
  if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if B is odd then */
    if (mp_isodd (&B) == 1) {
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* B = B/2 */
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if D is odd then */
    if (mp_isodd (&D) == 1) {
      /* D = (D-x)/2 */
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* D = D/2 */
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0) {
    goto top;
  }

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* b is now the inverse */
  neg = a->sign;
  while (D.sign == MP_NEG) {
    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }
  mp_exch (&D, c);
  c->sign = neg;
  res = MP_OKAY;

LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
  return res;
}
#endif

/* End: bn_fast_mp_invmod.c */

/* Start: bn_fast_mp_montgomery_reduce.c */
#include <tommath.h>
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes xR**-1 == x (mod N) via Montgomery Reduction
 *
 * This is an optimized implementation of montgomery_reduce
 * which uses the comba method to quickly calculate the columns of the
 * reduction.
 *
 * Based on Algorithm 14.32 on pp.601 of HAC.
*/
int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
{
  int     ix, res, olduse;
  mp_word W[MP_WARRAY];

  /* get old used count */
  olduse = x->used;

  /* grow a as required */
  if (x->alloc < n->used + 1) {
    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* first we have to get the digits of the input into
   * an array of double precision words W[...]
   */
  {
    register mp_word *_W;
    register mp_digit *tmpx;

    /* alias for the W[] array */
    _W   = W;

    /* alias for the digits of  x*/
    tmpx = x->dp;

    /* copy the digits of a into W[0..a->used-1] */
    for (ix = 0; ix < x->used; ix++) {
      *_W++ = *tmpx++;
    }

    /* zero the high words of W[a->used..m->used*2] */
    for (; ix < n->used * 2 + 1; ix++) {
      *_W++ = 0;
    }
  }

  /* now we proceed to zero successive digits
   * from the least significant upwards
   */
  for (ix = 0; ix < n->used; ix++) {
    /* mu = ai * m' mod b
     *
     * We avoid a double precision multiplication (which isn't required)
     * by casting the value down to a mp_digit.  Note this requires
     * that W[ix-1] have  the carry cleared (see after the inner loop)
     */
    register mp_digit mu;
    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);

    /* a = a + mu * m * b**i
     *
     * This is computed in place and on the fly.  The multiplication
     * by b**i is handled by offseting which columns the results
     * are added to.
     *
     * Note the comba method normally doesn't handle carries in the
     * inner loop In this case we fix the carry from the previous
     * column since the Montgomery reduction requires digits of the
     * result (so far) [see above] to work.  This is
     * handled by fixing up one carry after the inner loop.  The
     * carry fixups are done in order so after these loops the
     * first m->used words of W[] have the carries fixed
     */
    {
      register int iy;
      register mp_digit *tmpn;
      register mp_word *_W;

      /* alias for the digits of the modulus */
      tmpn = n->dp;

      /* Alias for the columns set by an offset of ix */
      _W = W + ix;

      /* inner loop */
      for (iy = 0; iy < n->used; iy++) {
          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
      }
    }

    /* now fix carry for next digit, W[ix+1] */
    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
  }

  /* now we have to propagate the carries and
   * shift the words downward [all those least
   * significant digits we zeroed].
   */
  {
    register mp_digit *tmpx;
    register mp_word *_W, *_W1;

    /* nox fix rest of carries */

    /* alias for current word */
    _W1 = W + ix;

    /* alias for next word, where the carry goes */
    _W = W + ++ix;

    for (; ix <= n->used * 2 + 1; ix++) {
      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
    }

    /* copy out, A = A/b**n
     *
     * The result is A/b**n but instead of converting from an
     * array of mp_word to mp_digit than calling mp_rshd
     * we just copy them in the right order
     */

    /* alias for destination word */
    tmpx = x->dp;

    /* alias for shifted double precision result */
    _W = W + n->used;

    for (ix = 0; ix < n->used + 1; ix++) {
      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
    }

    /* zero oldused digits, if the input a was larger than
     * m->used+1 we'll have to clear the digits
     */
    for (; ix < olduse; ix++) {
      *tmpx++ = 0;
    }
  }

  /* set the max used and clamp */
  x->used = n->used + 1;
  mp_clamp (x);

  /* if A >= m then A = A - m */
  if (mp_cmp_mag (x, n) != MP_LT) {
    return s_mp_sub (x, n, x);
  }
  return MP_OKAY;
}
#endif

/* End: bn_fast_mp_montgomery_reduce.c */

/* Start: bn_fast_s_mp_mul_digs.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Fast (comba) multiplier
 *
 * This is the fast column-array [comba] multiplier.  It is 
 * designed to compute the columns of the product first 
 * then handle the carries afterwards.  This has the effect 
 * of making the nested loops that compute the columns very
 * simple and schedulable on super-scalar processors.
 *
 * This has been modified to produce a variable number of 
 * digits of output so if say only a half-product is required 
 * you don't have to compute the upper half (a feature 
 * required for fast Barrett reduction).
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 *
 */
int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  register mp_word  _W;

  /* grow the destination as required */
  if (c->alloc < digs) {
    if ((res = mp_grow (c, digs)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = MIN(digs, a->used + b->used);

  /* clear the carry */
  _W = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty;
      int      iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; ++iz) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);

      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
 }

  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;
    tmpc = c->dp;
    for (ix = 0; ix < pa+1; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_mul_digs.c */

/* Start: bn_fast_s_mp_mul_high_digs.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* this is a modified version of fast_s_mul_digs that only produces
 * output digits *above* digs.  See the comments for fast_s_mul_digs
 * to see how it works.
 *
 * This is used in the Barrett reduction since for one of the multiplications
 * only the higher digits were needed.  This essentially halves the work.
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 */
int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  mp_word  _W;

  /* grow the destination as required */
  pa = a->used + b->used;
  if (c->alloc < pa) {
    if ((res = mp_grow (c, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = a->used + b->used;
  _W = 0;
  for (ix = digs; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
  }
  
  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;

    tmpc = c->dp + digs;
    for (ix = digs; ix < pa; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_mul_high_digs.c */

/* Start: bn_fast_s_mp_sqr.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* the jist of squaring...
 * you do like mult except the offset of the tmpx [one that 
 * starts closer to zero] can't equal the offset of tmpy.  
 * So basically you set up iy like before then you min it with
 * (ty-tx) so that it never happens.  You double all those 
 * you add in the inner loop

After that loop you do the squares and add them in.
*/

int fast_s_mp_sqr (mp_int * a, mp_int * b)
{
  int       olduse, res, pa, ix, iz;
  mp_digit   W[MP_WARRAY], *tmpx;
  mp_word   W1;

  /* grow the destination as required */
  pa = a->used + a->used;
  if (b->alloc < pa) {
    if ((res = mp_grow (b, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  W1 = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_word  _W;
      mp_digit *tmpy;

      /* clear counter */
      _W = 0;

      /* get offsets into the two bignums */
      ty = MIN(a->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = a->dp + ty;

      /* this is the number of times the loop will iterrate, essentially
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* now for squaring tx can never equal ty 
       * we halve the distance since they approach at a rate of 2x
       * and we have to round because odd cases need to be executed
       */
      iy = MIN(iy, (ty-tx+1)>>1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* double the inner product and add carry */
      _W = _W + _W + W1;

      /* even columns have the square term in them */
      if ((ix&1) == 0) {
         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
      }

      /* store it */
      W[ix] = (mp_digit)(_W & MP_MASK);

      /* make next carry */
      W1 = _W >> ((mp_word)DIGIT_BIT);
  }

  /* setup dest */
  olduse  = b->used;
  b->used = a->used+a->used;

  {
    mp_digit *tmpb;
    tmpb = b->dp;
    for (ix = 0; ix < pa; ix++) {
      *tmpb++ = W[ix] & MP_MASK;
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpb++ = 0;
    }
  }
  mp_clamp (b);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_sqr.c */

/* Start: bn_mp_2expt.c */
#include <tommath.h>
#ifdef BN_MP_2EXPT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes a = 2**b 
 *
 * Simple algorithm which zeroes the int, grows it then just sets one bit
 * as required.
 */
int
mp_2expt (mp_int * a, int b)
{
  int     res;

  /* zero a as per default */
  mp_zero (a);

  /* grow a to accomodate the single bit */
  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
    return res;
  }

  /* set the used count of where the bit will go */
  a->used = b / DIGIT_BIT + 1;

  /* put the single bit in its place */
  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);

  return MP_OKAY;
}
#endif

/* End: bn_mp_2expt.c */

/* Start: bn_mp_abs.c */
#include <tommath.h>
#ifdef BN_MP_ABS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* b = |a| 
 *
 * Simple function copies the input and fixes the sign to positive
 */
int
mp_abs (mp_int * a, mp_int * b)
{
  int     res;

  /* copy a to b */
  if (a != b) {
     if ((res = mp_copy (a, b)) != MP_OKAY) {
       return res;
     }
  }

  /* force the sign of b to positive */
  b->sign = MP_ZPOS;

  return MP_OKAY;
}
#endif

/* End: bn_mp_abs.c */

/* Start: bn_mp_add.c */
#include <tommath.h>
#ifdef BN_MP_ADD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* high level addition (handles signs) */
int mp_add (mp_int * a, mp_int * b, mp_int * c)
{
  int     sa, sb, res;

  /* get sign of both inputs */
  sa = a->sign;
  sb = b->sign;

  /* handle two cases, not four */
  if (sa == sb) {
    /* both positive or both negative */
    /* add their magnitudes, copy the sign */
    c->sign = sa;
    res = s_mp_add (a, b, c);
  } else {
    /* one positive, the other negative */
    /* subtract the one with the greater magnitude from */
    /* the one of the lesser magnitude.  The result gets */
    /* the sign of the one with the greater magnitude. */
    if (mp_cmp_mag (a, b) == MP_LT) {
      c->sign = sb;
      res = s_mp_sub (b, a, c);
    } else {
      c->sign = sa;
      res = s_mp_sub (a, b, c);
    }
  }
  return res;
}

#endif

/* End: bn_mp_add.c */

/* Start: bn_mp_add_d.c */
#include <tommath.h>
#ifdef BN_MP_ADD_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* single digit addition */
int
mp_add_d (mp_int * a, mp_digit b, mp_int * c)
{
  int     res, ix, oldused;
  mp_digit *tmpa, *tmpc, mu;

  /* grow c as required */
  if (c->alloc < a->used + 1) {
     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
        return res;
     }
  }

  /* if a is negative and |a| >= b, call c = |a| - b */
  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
     /* temporarily fix sign of a */
     a->sign = MP_ZPOS;

     /* c = |a| - b */
     res = mp_sub_d(a, b, c);

     /* fix sign  */
     a->sign = c->sign = MP_NEG;

     /* clamp */
     mp_clamp(c);

     return res;
  }

  /* old number of used digits in c */
  oldused = c->used;

  /* sign always positive */
  c->sign = MP_ZPOS;

  /* source alias */
  tmpa    = a->dp;

  /* destination alias */
  tmpc    = c->dp;

  /* if a is positive */
  if (a->sign == MP_ZPOS) {
     /* add digit, after this we're propagating
      * the carry.
      */
     *tmpc   = *tmpa++ + b;
     mu      = *tmpc >> DIGIT_BIT;
     *tmpc++ &= MP_MASK;

     /* now handle rest of the digits */
     for (ix = 1; ix < a->used; ix++) {
        *tmpc   = *tmpa++ + mu;
        mu      = *tmpc >> DIGIT_BIT;
        *tmpc++ &= MP_MASK;
     }
     /* set final carry */
     ix++;
     *tmpc++  = mu;

     /* setup size */
     c->used = a->used + 1;
  } else {
     /* a was negative and |a| < b */
     c->used  = 1;

     /* the result is a single digit */
     if (a->used == 1) {
        *tmpc++  =  b - a->dp[0];
     } else {
        *tmpc++  =  b;
     }

     /* setup count so the clearing of oldused
      * can fall through correctly
      */
     ix       = 1;
  }

  /* now zero to oldused */
  while (ix++ < oldused) {
     *tmpc++ = 0;
  }
  mp_clamp(c);

  return MP_OKAY;
}

#endif

/* End: bn_mp_add_d.c */

/* Start: bn_mp_addmod.c */
#include <tommath.h>
#ifdef BN_MP_ADDMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* d = a + b (mod c) */
int
mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_addmod.c */

/* Start: bn_mp_and.c */
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* AND two ints together */
int
mp_and (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] &= x->dp[ix];
  }

  /* zero digits above the last from the smallest mp_int */
  for (; ix < t.used; ix++) {
    t.dp[ix] = 0;
  }

  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_and.c */

/* Start: bn_mp_clamp.c */
#include <tommath.h>
#ifdef BN_MP_CLAMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* trim unused digits 
 *
 * This is used to ensure that leading zero digits are
 * trimed and the leading "used" digit will be non-zero
 * Typically very fast.  Also fixes the sign if there
 * are no more leading digits
 */
void
mp_clamp (mp_int * a)
{
  /* decrease used while the most significant digit is
   * zero.
   */
  while (a->used > 0 && a->dp[a->used - 1] == 0) {
    --(a->used);
  }

  /* reset the sign flag if used == 0 */
  if (a->used == 0) {
    a->sign = MP_ZPOS;
  }
}
#endif

/* End: bn_mp_clamp.c */

/* Start: bn_mp_clear.c */
#include <tommath.h>
#ifdef BN_MP_CLEAR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* clear one (frees)  */
void
mp_clear (mp_int * a)
{
  int i;

  /* only do anything if a hasn't been freed previously */
  if (a->dp != NULL) {
    /* first zero the digits */
    for (i = 0; i < a->used; i++) {
        a->dp[i] = 0;
    }

    /* free ram */
    XFREE(a->dp);

    /* reset members to make debugging easier */
    a->dp    = NULL;
    a->alloc = a->used = 0;
    a->sign  = MP_ZPOS;
  }
}
#endif

/* End: bn_mp_clear.c */

/* Start: bn_mp_clear_multi.c */
#include <tommath.h>
#ifdef BN_MP_CLEAR_MULTI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#include <stdarg.h>

void mp_clear_multi(mp_int *mp, ...) 
{
    mp_int* next_mp = mp;
    va_list args;
    va_start(args, mp);
    while (next_mp != NULL) {
        mp_clear(next_mp);
        next_mp = va_arg(args, mp_int*);
    }
    va_end(args);
}
#endif

/* End: bn_mp_clear_multi.c */

/* Start: bn_mp_cmp.c */
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare two ints (signed)*/
int
mp_cmp (mp_int * a, mp_int * b)
{
  /* compare based on sign */
  if (a->sign != b->sign) {
     if (a->sign == MP_NEG) {
        return MP_LT;
     } else {
        return MP_GT;
     }
  }
  
  /* compare digits */
  if (a->sign == MP_NEG) {
     /* if negative compare opposite direction */
     return mp_cmp_mag(b, a);
  } else {
     return mp_cmp_mag(a, b);
  }
}
#endif

/* End: bn_mp_cmp.c */

/* Start: bn_mp_cmp_d.c */
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare a digit */
int mp_cmp_d(mp_int * a, mp_digit b)
{
  /* compare based on sign */
  if (a->sign == MP_NEG) {
    return MP_LT;
  }

  /* compare based on magnitude */
  if (a->used > 1) {
    return MP_GT;
  }

  /* compare the only digit of a to b */
  if (a->dp[0] > b) {
    return MP_GT;
  } else if (a->dp[0] < b) {
    return MP_LT;
  } else {
    return MP_EQ;
  }
}
#endif

/* End: bn_mp_cmp_d.c */

/* Start: bn_mp_cmp_mag.c */
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* compare maginitude of two ints (unsigned) */
int mp_cmp_mag (mp_int * a, mp_int * b)
{
  int     n;
  mp_digit *tmpa, *tmpb;

  /* compare based on # of non-zero digits */
  if (a->used > b->used) {
    return MP_GT;
  }
  
  if (a->used < b->used) {
    return MP_LT;
  }

  /* alias for a */
  tmpa = a->dp + (a->used - 1);

  /* alias for b */
  tmpb = b->dp + (a->used - 1);

  /* compare based on digits  */
  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
    if (*tmpa > *tmpb) {
      return MP_GT;
    }

    if (*tmpa < *tmpb) {
      return MP_LT;
    }
  }
  return MP_EQ;
}
#endif

/* End: bn_mp_cmp_mag.c */

/* Start: bn_mp_cnt_lsb.c */
#include <tommath.h>
#ifdef BN_MP_CNT_LSB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

static const int lnz[16] = { 
   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a)
{
   int x;
   mp_digit q, qq;

   /* easy out */
   if (mp_iszero(a) == 1) {
      return 0;
   }

   /* scan lower digits until non-zero */
   for (x = 0; x < a->used && a->dp[x] == 0; x++);
   q = a->dp[x];
   x *= DIGIT_BIT;

   /* now scan this digit until a 1 is found */
   if ((q & 1) == 0) {
      do {
         qq  = q & 15;
         x  += lnz[qq];
         q >>= 4;
      } while (qq == 0);
   }
   return x;
}

#endif

/* End: bn_mp_cnt_lsb.c */

/* Start: bn_mp_copy.c */
#include <tommath.h>
#ifdef BN_MP_COPY_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* copy, b = a */
int
mp_copy (mp_int * a, mp_int * b)
{
  int     res, n;

  /* if dst == src do nothing */
  if (a == b) {
    return MP_OKAY;
  }

  /* grow dest */
  if (b->alloc < a->used) {
     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
        return res;
     }
  }

  /* zero b and copy the parameters over */
  {
    register mp_digit *tmpa, *tmpb;

    /* pointer aliases */

    /* source */
    tmpa = a->dp;

    /* destination */
    tmpb = b->dp;

    /* copy all the digits */
    for (n = 0; n < a->used; n++) {
      *tmpb++ = *tmpa++;
    }

    /* clear high digits */
    for (; n < b->used; n++) {
      *tmpb++ = 0;
    }
  }

  /* copy used count and sign */
  b->used = a->used;
  b->sign = a->sign;
  return MP_OKAY;
}
#endif

/* End: bn_mp_copy.c */

/* Start: bn_mp_count_bits.c */
#include <tommath.h>
#ifdef BN_MP_COUNT_BITS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* returns the number of bits in an int */
int
mp_count_bits (mp_int * a)
{
  int     r;
  mp_digit q;

  /* shortcut */
  if (a->used == 0) {
    return 0;
  }

  /* get number of digits and add that */
  r = (a->used - 1) * DIGIT_BIT;
  
  /* take the last digit and count the bits in it */
  q = a->dp[a->used - 1];
  while (q > ((mp_digit) 0)) {
    ++r;
    q >>= ((mp_digit) 1);
  }
  return r;
}
#endif

/* End: bn_mp_count_bits.c */

/* Start: bn_mp_div.c */
#include <tommath.h>
#ifdef BN_MP_DIV_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

#ifdef BN_MP_DIV_SMALL

/* slower bit-bang division... also smaller */
int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
   mp_int ta, tb, tq, q;
   int    res, n, n2;

  /* is divisor zero ? */
  if (mp_iszero (b) == 1) {
    return MP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (mp_cmp_mag (a, b) == MP_LT) {
    if (d != NULL) {
      res = mp_copy (a, d);
    } else {
      res = MP_OKAY;
    }
    if (c != NULL) {
      mp_zero (c);
    }
    return res;
  }
	
  /* init our temps */
  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
     return res;
  }


  mp_set(&tq, 1);
  n = mp_count_bits(a) - mp_count_bits(b);
  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
      goto LBL_ERR;
  }

  while (n-- >= 0) {
     if (mp_cmp(&tb, &ta) != MP_GT) {
        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
           goto LBL_ERR;
        }
     }
     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
           goto LBL_ERR;
     }
  }

  /* now q == quotient and ta == remainder */
  n  = a->sign;
  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
  if (c != NULL) {
     mp_exch(c, &q);
     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
  }
  if (d != NULL) {
     mp_exch(d, &ta);
     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
  }
LBL_ERR:
   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
   return res;
}

#else

/* integer signed division. 
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
 * HAC pp.598 Algorithm 14.20
 *
 * Note that the description in HAC is horribly 
 * incomplete.  For example, it doesn't consider 
 * the case where digits are removed from 'x' in 
 * the inner loop.  It also doesn't consider the 
 * case that y has fewer than three digits, etc..
 *
 * The overall algorithm is as described as 
 * 14.20 from HAC but fixed to treat these cases.
*/
int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  mp_int  q, x, y, t1, t2;
  int     res, n, t, i, norm, neg;

  /* is divisor zero ? */
  if (mp_iszero (b) == 1) {
    return MP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (mp_cmp_mag (a, b) == MP_LT) {
    if (d != NULL) {
      res = mp_copy (a, d);
    } else {
      res = MP_OKAY;
    }
    if (c != NULL) {
      mp_zero (c);
    }
    return res;
  }

  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
    return res;
  }
  q.used = a->used + 2;

  if ((res = mp_init (&t1)) != MP_OKAY) {
    goto LBL_Q;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
    goto LBL_T2;
  }

  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
    goto LBL_X;
  }

  /* fix the sign */
  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  x.sign = y.sign = MP_ZPOS;

  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
  norm = mp_count_bits(&y) % DIGIT_BIT;
  if (norm < (int)(DIGIT_BIT-1)) {
     norm = (DIGIT_BIT-1) - norm;
     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
       goto LBL_Y;
     }
     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
       goto LBL_Y;
     }
  } else {
     norm = 0;
  }

  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  n = x.used - 1;
  t = y.used - 1;

  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
    goto LBL_Y;
  }

  while (mp_cmp (&x, &y) != MP_LT) {
    ++(q.dp[n - t]);
    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
      goto LBL_Y;
    }
  }

  /* reset y by shifting it back down */
  mp_rshd (&y, n - t);

  /* step 3. for i from n down to (t + 1) */
  for (i = n; i >= (t + 1); i--) {
    if (i > x.used) {
      continue;
    }

    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
    if (x.dp[i] == y.dp[t]) {
      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
    } else {
      mp_word tmp;
      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
      tmp |= ((mp_word) x.dp[i - 1]);
      tmp /= ((mp_word) y.dp[t]);
      if (tmp > (mp_word) MP_MASK)
        tmp = MP_MASK;
      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
    }

    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
             xi * b**2 + xi-1 * b + xi-2 
     
       do q{i-t-1} -= 1; 
    */
    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
    do {
      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;

      /* find left hand */
      mp_zero (&t1);
      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
      t1.dp[1] = y.dp[t];
      t1.used = 2;
      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
        goto LBL_Y;
      }

      /* find right hand */
      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
      t2.dp[2] = x.dp[i];
      t2.used = 3;
    } while (mp_cmp_mag(&t1, &t2) == MP_GT);

    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
      goto LBL_Y;
    }

    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
    if (x.sign == MP_NEG) {
      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
        goto LBL_Y;
      }

      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
    }
  }

  /* now q is the quotient and x is the remainder 
   * [which we have to normalize] 
   */
  
  /* get sign before writing to c */
  x.sign = x.used == 0 ? MP_ZPOS : a->sign;

  if (c != NULL) {
    mp_clamp (&q);
    mp_exch (&q, c);
    c->sign = neg;
  }

  if (d != NULL) {
    mp_div_2d (&x, norm, &x, NULL);
    mp_exch (&x, d);
  }

  res = MP_OKAY;

LBL_Y:mp_clear (&y);
LBL_X:mp_clear (&x);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
LBL_Q:mp_clear (&q);
  return res;
}

#endif

#endif

/* End: bn_mp_div.c */

/* Start: bn_mp_div_2.c */
#include <tommath.h>
#ifdef BN_MP_DIV_2_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* b = a/2 */
int mp_div_2(mp_int * a, mp_int * b)
{
  int     x, res, oldused;

  /* copy */
  if (b->alloc < a->used) {
    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
      return res;
    }
  }

  oldused = b->used;
  b->used = a->used;
  {
    register mp_digit r, rr, *tmpa, *tmpb;

    /* source alias */
    tmpa = a->dp + b->used - 1;

    /* dest alias */
    tmpb = b->dp + b->used - 1;

    /* carry */
    r = 0;
    for (x = b->used - 1; x >= 0; x--) {
      /* get the carry for the next iteration */
      rr = *tmpa & 1;

      /* shift the current digit, add in carry and store */
      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));

      /* forward carry to next iteration */
      r = rr;
    }

    /* zero excess digits */
    tmpb = b->dp + b->used;
    for (x = b->used; x < oldused; x++) {
      *tmpb++ = 0;
    }
  }
  b->sign = a->sign;
  mp_clamp (b);
  return MP_OKAY;
}
#endif

/* End: bn_mp_div_2.c */

/* Start: bn_mp_div_2d.c */
#include <tommath.h>
#ifdef BN_MP_DIV_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
{
  mp_digit D, r, rr;
  int     x, res;
  mp_int  t;


  /* if the shift count is <= 0 then we do no work */
  if (b <= 0) {
    res = mp_copy (a, c);
    if (d != NULL) {
      mp_zero (d);
    }
    return res;
  }

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  /* get the remainder */
  if (d != NULL) {
    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
  }

  /* copy */
  if ((res = mp_copy (a, c)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }

  /* shift by as many digits in the bit count */
  if (b >= (int)DIGIT_BIT) {
    mp_rshd (c, b / DIGIT_BIT);
  }

  /* shift any bit count < DIGIT_BIT */
  D = (mp_digit) (b % DIGIT_BIT);
  if (D != 0) {
    register mp_digit *tmpc, mask, shift;

    /* mask */
    mask = (((mp_digit)1) << D) - 1;

    /* shift for lsb */
    shift = DIGIT_BIT - D;

    /* alias */
    tmpc = c->dp + (c->used - 1);

    /* carry */
    r = 0;
    for (x = c->used - 1; x >= 0; x--) {
      /* get the lower  bits of this word in a temp */
      rr = *tmpc & mask;

      /* shift the current word and mix in the carry bits from the previous word */
      *tmpc = (*tmpc >> D) | (r << shift);
      --tmpc;

      /* set the carry to the carry bits of the current word found above */
      r = rr;
    }
  }
  mp_clamp (c);
  if (d != NULL) {
    mp_exch (&t, d);
  }
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_div_2d.c */

/* Start: bn_mp_div_3.c */
#include <tommath.h>
#ifdef BN_MP_DIV_3_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* divide by three (based on routine from MPI and the GMP manual) */
int
mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
{
  mp_int   q;
  mp_word  w, t;
  mp_digit b;
  int      res, ix;
  
  /* b = 2**DIGIT_BIT / 3 */
  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);

  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
     return res;
  }
  
  q.used = a->used;
  q.sign = a->sign;
  w = 0;
  for (ix = a->used - 1; ix >= 0; ix--) {
     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);

     if (w >= 3) {
        /* multiply w by [1/3] */
        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);

        /* now subtract 3 * [w/3] from w, to get the remainder */
        w -= t+t+t;

        /* fixup the remainder as required since
         * the optimization is not exact.
         */
        while (w >= 3) {
           t += 1;
           w -= 3;
        }
      } else {
        t = 0;
      }
      q.dp[ix] = (mp_digit)t;
  }

  /* [optional] store the remainder */
  if (d != NULL) {
     *d = (mp_digit)w;
  }

  /* [optional] store the quotient */
  if (c != NULL) {
     mp_clamp(&q);
     mp_exch(&q, c);
  }
  mp_clear(&q);
  
  return res;
}

#endif

/* End: bn_mp_div_3.c */

/* Start: bn_mp_div_d.c */
#include <tommath.h>
#ifdef BN_MP_DIV_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

static int s_is_power_of_two(mp_digit b, int *p)
{
   int x;

   /* fast return if no power of two */
   if ((b==0) || (b & (b-1))) {
      return 0;
   }

   for (x = 0; x < DIGIT_BIT; x++) {
      if (b == (((mp_digit)1)<<x)) {
         *p = x;
         return 1;
      }
   }
   return 0;
}

/* single digit division (based on routine from MPI) */
int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
{
  mp_int  q;
  mp_word w;
  mp_digit t;
  int     res, ix;

  /* cannot divide by zero */
  if (b == 0) {
     return MP_VAL;
  }

  /* quick outs */
  if (b == 1 || mp_iszero(a) == 1) {
     if (d != NULL) {
        *d = 0;
     }
     if (c != NULL) {
        return mp_copy(a, c);
     }
     return MP_OKAY;
  }

  /* power of two ? */
  if (s_is_power_of_two(b, &ix) == 1) {
     if (d != NULL) {
        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
     }
     if (c != NULL) {
        return mp_div_2d(a, ix, c, NULL);
     }
     return MP_OKAY;
  }

#ifdef BN_MP_DIV_3_C
  /* three? */
  if (b == 3) {
     return mp_div_3(a, c, d);
  }
#endif

  /* no easy answer [c'est la vie].  Just division */
  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
     return res;
  }
  
  q.used = a->used;
  q.sign = a->sign;
  w = 0;
  for (ix = a->used - 1; ix >= 0; ix--) {
     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
     
     if (w >= b) {
        t = (mp_digit)(w / b);
        w -= ((mp_word)t) * ((mp_word)b);
      } else {
        t = 0;
      }
      q.dp[ix] = (mp_digit)t;
  }
  
  if (d != NULL) {
     *d = (mp_digit)w;
  }
  
  if (c != NULL) {
     mp_clamp(&q);
     mp_exch(&q, c);
  }
  mp_clear(&q);
  
  return res;
}

#endif

/* End: bn_mp_div_d.c */

/* Start: bn_mp_dr_is_modulus.c */
#include <tommath.h>
#ifdef BN_MP_DR_IS_MODULUS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines if a number is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a)
{
   int ix;

   /* must be at least two digits */
   if (a->used < 2) {
      return 0;
   }

   /* must be of the form b**k - a [a <= b] so all
    * but the first digit must be equal to -1 (mod b).
    */
   for (ix = 1; ix < a->used; ix++) {
       if (a->dp[ix] != MP_MASK) {
          return 0;
       }
   }
   return 1;
}

#endif

/* End: bn_mp_dr_is_modulus.c */

/* Start: bn_mp_dr_reduce.c */
#include <tommath.h>
#ifdef BN_MP_DR_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
 *
 * Based on algorithm from the paper
 *
 * "Generating Efficient Primes for Discrete Log Cryptosystems"
 *                 Chae Hoon Lim, Pil Joong Lee,
 *          POSTECH Information Research Laboratories
 *
 * The modulus must be of a special format [see manual]
 *
 * Has been modified to use algorithm 7.10 from the LTM book instead
 *
 * Input x must be in the range 0 <= x <= (n-1)**2
 */
int
mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
{
  int      err, i, m;
  mp_word  r;
  mp_digit mu, *tmpx1, *tmpx2;

  /* m = digits in modulus */
  m = n->used;

  /* ensure that "x" has at least 2m digits */
  if (x->alloc < m + m) {
    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
      return err;
    }
  }

/* top of loop, this is where the code resumes if
 * another reduction pass is required.
 */
top:
  /* aliases for digits */
  /* alias for lower half of x */
  tmpx1 = x->dp;

  /* alias for upper half of x, or x/B**m */
  tmpx2 = x->dp + m;

  /* set carry to zero */
  mu = 0;

  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
  for (i = 0; i < m; i++) {
      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
      *tmpx1++  = (mp_digit)(r & MP_MASK);
      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
  }

  /* set final carry */
  *tmpx1++ = mu;

  /* zero words above m */
  for (i = m + 1; i < x->used; i++) {
      *tmpx1++ = 0;
  }

  /* clamp, sub and return */
  mp_clamp (x);

  /* if x >= n then subtract and reduce again
   * Each successive "recursion" makes the input smaller and smaller.
   */
  if (mp_cmp_mag (x, n) != MP_LT) {
    s_mp_sub(x, n, x);
    goto top;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_dr_reduce.c */

/* Start: bn_mp_dr_setup.c */
#include <tommath.h>
#ifdef BN_MP_DR_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines the setup value */
void mp_dr_setup(mp_int *a, mp_digit *d)
{
   /* the casts are required if DIGIT_BIT is one less than
    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
    */
   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
        ((mp_word)a->dp[0]));
}

#endif

/* End: bn_mp_dr_setup.c */

/* Start: bn_mp_exch.c */
#include <tommath.h>
#ifdef BN_MP_EXCH_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* swap the elements of two integers, for cases where you can't simply swap the 
 * mp_int pointers around
 */
void
mp_exch (mp_int * a, mp_int * b)
{
  mp_int  t;

  t  = *a;
  *a = *b;
  *b = t;
}
#endif

/* End: bn_mp_exch.c */

/* Start: bn_mp_expt_d.c */
#include <tommath.h>
#ifdef BN_MP_EXPT_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* calculate c = a**b  using a square-multiply algorithm */
int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
{
  int     res, x;
  mp_int  g;

  if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
    return res;
  }

  /* set initial result */
  mp_set (c, 1);

  for (x = 0; x < (int) DIGIT_BIT; x++) {
    /* square */
    if ((res = mp_sqr (c, c)) != MP_OKAY) {
      mp_clear (&g);
      return res;
    }

    /* if the bit is set multiply */
    if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
      if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
         mp_clear (&g);
         return res;
      }
    }

    /* shift to next bit */
    b <<= 1;
  }

  mp_clear (&g);
  return MP_OKAY;
}
#endif

/* End: bn_mp_expt_d.c */

/* Start: bn_mp_exptmod.c */
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */


/* this is a shell function that calls either the normal or Montgomery
 * exptmod functions.  Originally the call to the montgomery code was
 * embedded in the normal function but that wasted alot of stack space
 * for nothing (since 99% of the time the Montgomery code would be called)
 */
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  int dr;

  /* modulus P must be positive */
  if (P->sign == MP_NEG) {
     return MP_VAL;
  }

  /* if exponent X is negative we have to recurse */
  if (X->sign == MP_NEG) {
#ifdef BN_MP_INVMOD_C
     mp_int tmpG, tmpX;
     int err;

     /* first compute 1/G mod P */
     if ((err = mp_init(&tmpG)) != MP_OKAY) {
        return err;
     }
     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }

     /* now get |X| */
     if ((err = mp_init(&tmpX)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }
     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
        mp_clear_multi(&tmpG, &tmpX, NULL);
        return err;
     }

     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
     err = mp_exptmod(&tmpG, &tmpX, P, Y);
     mp_clear_multi(&tmpG, &tmpX, NULL);
     return err;
#else 
     /* no invmod */
     return MP_VAL;
#endif
  }

/* modified diminished radix reduction */
#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
  if (mp_reduce_is_2k_l(P) == MP_YES) {
     return s_mp_exptmod(G, X, P, Y, 1);
  }
#endif

#ifdef BN_MP_DR_IS_MODULUS_C
  /* is it a DR modulus? */
  dr = mp_dr_is_modulus(P);
#else
  /* default to no */
  dr = 0;
#endif

#ifdef BN_MP_REDUCE_IS_2K_C
  /* if not, is it a unrestricted DR modulus? */
  if (dr == 0) {
     dr = mp_reduce_is_2k(P) << 1;
  }
#endif
    
  /* if the modulus is odd or dr != 0 use the montgomery method */
#ifdef BN_MP_EXPTMOD_FAST_C
  if (mp_isodd (P) == 1 || dr !=  0) {
    return mp_exptmod_fast (G, X, P, Y, dr);
  } else {
#endif
#ifdef BN_S_MP_EXPTMOD_C
    /* otherwise use the generic Barrett reduction technique */
    return s_mp_exptmod (G, X, P, Y, 0);
#else
    /* no exptmod for evens */
    return MP_VAL;
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
  }
#endif
}

#endif

/* End: bn_mp_exptmod.c */

/* Start: bn_mp_exptmod_fast.c */
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_FAST_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
 *
 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
 * The value of k changes based on the size of the exponent.
 *
 * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
 */

#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
{
  mp_int  M[TAB_SIZE], res;
  mp_digit buf, mp;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* use a pointer to the reduction algorithm.  This allows us to use
   * one of many reduction algorithms without modding the guts of
   * the code with if statements everywhere.
   */
  int     (*redux)(mp_int*,mp_int*,mp_digit);

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
  if (winsize > 5) {
     winsize = 5;
  }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err;
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* determine and setup reduction code */
  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_SETUP_C     
     /* now setup montgomery  */
     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
#else
     err = MP_VAL;
     goto LBL_M;
#endif

     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
     if (((P->used * 2 + 1) < MP_WARRAY) &&
          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
        redux = fast_mp_montgomery_reduce;
     } else 
#endif
     {
#ifdef BN_MP_MONTGOMERY_REDUCE_C
        /* use slower baseline Montgomery method */
        redux = mp_montgomery_reduce;
#else
        err = MP_VAL;
        goto LBL_M;
#endif
     }
  } else if (redmode == 1) {
#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
     /* setup DR reduction for moduli of the form B**k - b */
     mp_dr_setup(P, &mp);
     redux = mp_dr_reduce;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  } else {
#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
     /* setup DR reduction for moduli of the form 2**k - b */
     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
     redux = mp_reduce_2k;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_M;
  }

  /* create M table
   *

   *
   * The first half of the table is not computed though accept for M[0] and M[1]
   */

  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
     /* now we need R mod m */
     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
       goto LBL_RES;
     }
#else 
     err = MP_VAL;
     goto LBL_RES;
#endif

     /* now set M[1] to G * R mod m */
     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
       goto LBL_RES;
     }
  } else {
     mp_set(&res, 1);
     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
        goto LBL_RES;
     }
  }

  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_RES;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* create upper table */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits so break */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int)DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* get next bit of the window */
      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  if (redmode == 0) {
     /* fixup result if Montgomery reduction is used
      * recall that any value in a Montgomery system is
      * actually multiplied by R mod n.  So we have
      * to reduce one more time to cancel out the factor
      * of R.
      */
     if ((err = redux(&res, P, mp)) != MP_OKAY) {
       goto LBL_RES;
     }
  }

  /* swap res with Y */
  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif

/* End: bn_mp_exptmod_fast.c */

/* Start: bn_mp_exteuclid.c */
#include <tommath.h>
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Extended euclidean algorithm of (a, b) produces 
   a*u1 + b*u2 = u3
 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
   int err;

   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }

   /* initialize, (v1,v2,v3) = (0,1,b) */
   mp_set(&v2, 1);
   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }

   /* loop while v3 != 0 */
   while (mp_iszero(&v3) == MP_NO) {
       /* q = u3/v3 */
       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }

       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }

       /* (u1,u2,u3) = (v1,v2,v3) */
       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }

       /* (v1,v2,v3) = (t1,t2,t3) */
       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
   }

   /* make sure U3 >= 0 */
   if (u3.sign == MP_NEG) {
      mp_neg(&u1, &u1);
      mp_neg(&u2, &u2);
      mp_neg(&u3, &u3);
   }

   /* copy result out */
   if (U1 != NULL) { mp_exch(U1, &u1); }
   if (U2 != NULL) { mp_exch(U2, &u2); }
   if (U3 != NULL) { mp_exch(U3, &u3); }

   err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
   return err;
}
#endif

/* End: bn_mp_exteuclid.c */

/* Start: bn_mp_fread.c */
#include <tommath.h>
#ifdef BN_MP_FREAD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* read a bigint from a file stream in ASCII */
int mp_fread(mp_int *a, int radix, FILE *stream)
{
   int err, ch, neg, y;
   
   /* clear a */
   mp_zero(a);
   
   /* if first digit is - then set negative */
   ch = fgetc(stream);
   if (ch == '-') {
      neg = MP_NEG;
      ch = fgetc(stream);
   } else {
      neg = MP_ZPOS;
   }
   
   for (;;) {
      /* find y in the radix map */
      for (y = 0; y < radix; y++) {
          if (mp_s_rmap[y] == ch) {
             break;
          }
      }
      if (y == radix) {
         break;
      }
      
      /* shift up and add */
      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
         return err;
      }
      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
         return err;
      }
      
      ch = fgetc(stream);
   }
   if (mp_cmp_d(a, 0) != MP_EQ) {
      a->sign = neg;
   }
   
   return MP_OKAY;
}

#endif

/* End: bn_mp_fread.c */

/* Start: bn_mp_fwrite.c */
#include <tommath.h>
#ifdef BN_MP_FWRITE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

int mp_fwrite(mp_int *a, int radix, FILE *stream)
{
   char *buf;
   int err, len, x;
   
   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
      return err;
   }

   buf = OPT_CAST(char) XMALLOC (len);
   if (buf == NULL) {
      return MP_MEM;
   }
   
   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
      XFREE (buf);
      return err;
   }
   
   for (x = 0; x < len; x++) {
       if (fputc(buf[x], stream) == EOF) {
          XFREE (buf);
          return MP_VAL;
       }
   }
   
   XFREE (buf);
   return MP_OKAY;
}

#endif

/* End: bn_mp_fwrite.c */

/* Start: bn_mp_gcd.c */
#include <tommath.h>
#ifdef BN_MP_GCD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Greatest Common Divisor using the binary method */
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  u, v;
  int     k, u_lsb, v_lsb, res;

  /* either zero than gcd is the largest */
  if (mp_iszero (a) == MP_YES) {
    return mp_abs (b, c);
  }
  if (mp_iszero (b) == MP_YES) {
    return mp_abs (a, c);
  }

  /* get copies of a and b we can modify */
  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
    goto LBL_U;
  }

  /* must be positive for the remainder of the algorithm */
  u.sign = v.sign = MP_ZPOS;

  /* B1.  Find the common power of two for u and v */
  u_lsb = mp_cnt_lsb(&u);
  v_lsb = mp_cnt_lsb(&v);
  k     = MIN(u_lsb, v_lsb);

  if (k > 0) {
     /* divide the power of two out */
     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }

     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  /* divide any remaining factors of two out */
  if (u_lsb != k) {
     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  if (v_lsb != k) {
     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  while (mp_iszero(&v) == 0) {
     /* make sure v is the largest */
     if (mp_cmp_mag(&u, &v) == MP_GT) {
        /* swap u and v to make sure v is >= u */
        mp_exch(&u, &v);
     }
     
     /* subtract smallest from largest */
     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
        goto LBL_V;
     }
     
     /* Divide out all factors of two */
     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     } 
  } 

  /* multiply by 2**k which we divided out at the beginning */
  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
     goto LBL_V;
  }
  c->sign = MP_ZPOS;
  res = MP_OKAY;
LBL_V:mp_clear (&u);
LBL_U:mp_clear (&v);
  return res;
}
#endif

/* End: bn_mp_gcd.c */

/* Start: bn_mp_get_int.c */
#include <tommath.h>
#ifdef BN_MP_GET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* get the lower 32-bits of an mp_int */
unsigned long mp_get_int(mp_int * a) 
{
  int i;
  unsigned long res;

  if (a->used == 0) {
     return 0;
  }

  /* get number of digits of the lsb we have to read */
  i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;

  /* get most significant digit of result */
  res = DIGIT(a,i);
   
  while (--i >= 0) {
    res = (res << DIGIT_BIT) | DIGIT(a,i);
  }

  /* force result to 32-bits always so it is consistent on non 32-bit platforms */
  return res & 0xFFFFFFFFUL;
}
#endif

/* End: bn_mp_get_int.c */

/* Start: bn_mp_grow.c */
#include <tommath.h>
#ifdef BN_MP_GROW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* grow as required */
int mp_grow (mp_int * a, int size)
{
  int     i;
  mp_digit *tmp;

  /* if the alloc size is smaller alloc more ram */
  if (a->alloc < size) {
    /* ensure there are always at least MP_PREC digits extra on top */
    size += (MP_PREC * 2) - (size % MP_PREC);

    /* reallocate the array a->dp
     *
     * We store the return in a temporary variable
     * in case the operation failed we don't want
     * to overwrite the dp member of a.
     */
    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
    if (tmp == NULL) {
      /* reallocation failed but "a" is still valid [can be freed] */
      return MP_MEM;
    }

    /* reallocation succeeded so set a->dp */
    a->dp = tmp;

    /* zero excess digits */
    i        = a->alloc;
    a->alloc = size;
    for (; i < a->alloc; i++) {
      a->dp[i] = 0;
    }
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_grow.c */

/* Start: bn_mp_init.c */
#include <tommath.h>
#ifdef BN_MP_INIT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* init a new mp_int */
int mp_init (mp_int * a)
{
  int i;

  /* allocate memory required and clear it */
  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
  if (a->dp == NULL) {
    return MP_MEM;
  }

  /* set the digits to zero */
  for (i = 0; i < MP_PREC; i++) {
      a->dp[i] = 0;
  }

  /* set the used to zero, allocated digits to the default precision
   * and sign to positive */
  a->used  = 0;
  a->alloc = MP_PREC;
  a->sign  = MP_ZPOS;

  return MP_OKAY;
}
#endif

/* End: bn_mp_init.c */

/* Start: bn_mp_init_copy.c */
#include <tommath.h>
#ifdef BN_MP_INIT_COPY_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* creates "a" then copies b into it */
int mp_init_copy (mp_int * a, mp_int * b)
{
  int     res;

  if ((res = mp_init (a)) != MP_OKAY) {
    return res;
  }
  return mp_copy (b, a);
}
#endif

/* End: bn_mp_init_copy.c */

/* Start: bn_mp_init_multi.c */
#include <tommath.h>
#ifdef BN_MP_INIT_MULTI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#include <stdarg.h>

int mp_init_multi(mp_int *mp, ...) 
{
    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
    int n = 0;                 /* Number of ok inits */
    mp_int* cur_arg = mp;
    va_list args;

    va_start(args, mp);        /* init args to next argument from caller */
    while (cur_arg != NULL) {
        if (mp_init(cur_arg) != MP_OKAY) {
            /* Oops - error! Back-track and mp_clear what we already
               succeeded in init-ing, then return error.
            */
            va_list clean_args;
            
            /* end the current list */
            va_end(args);
            
            /* now start cleaning up */            
            cur_arg = mp;
            va_start(clean_args, mp);
            while (n--) {
                mp_clear(cur_arg);
                cur_arg = va_arg(clean_args, mp_int*);
            }
            va_end(clean_args);
            res = MP_MEM;
            break;
        }
        n++;
        cur_arg = va_arg(args, mp_int*);
    }
    va_end(args);
    return res;                /* Assumed ok, if error flagged above. */
}

#endif

/* End: bn_mp_init_multi.c */

/* Start: bn_mp_init_set.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SET_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b)
{
  int err;
  if ((err = mp_init(a)) != MP_OKAY) {
     return err;
  }
  mp_set(a, b);
  return err;
}
#endif

/* End: bn_mp_init_set.c */

/* Start: bn_mp_init_set_int.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* initialize and set a digit */
int mp_init_set_int (mp_int * a, unsigned long b)
{
  int err;
  if ((err = mp_init(a)) != MP_OKAY) {
     return err;
  }
  return mp_set_int(a, b);
}
#endif

/* End: bn_mp_init_set_int.c */

/* Start: bn_mp_init_size.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* init an mp_init for a given size */
int mp_init_size (mp_int * a, int size)
{
  int x;

  /* pad size so there are always extra digits */
  size += (MP_PREC * 2) - (size % MP_PREC);	
  
  /* alloc mem */
  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
  if (a->dp == NULL) {
    return MP_MEM;
  }

  /* set the members */
  a->used  = 0;
  a->alloc = size;
  a->sign  = MP_ZPOS;

  /* zero the digits */
  for (x = 0; x < size; x++) {
      a->dp[x] = 0;
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_init_size.c */

/* Start: bn_mp_invmod.c */
#include <tommath.h>
#ifdef BN_MP_INVMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* hac 14.61, pp608 */
int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

#ifdef BN_FAST_MP_INVMOD_C
  /* if the modulus is odd we can use a faster routine instead */
  if (mp_isodd (b) == 1) {
    return fast_mp_invmod (a, b, c);
  }
#endif

#ifdef BN_MP_INVMOD_SLOW_C
  return mp_invmod_slow(a, b, c);
#endif

  return MP_VAL;
}
#endif

/* End: bn_mp_invmod.c */

/* Start: bn_mp_invmod_slow.c */
#include <tommath.h>
#ifdef BN_MP_INVMOD_SLOW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* hac 14.61, pp608 */
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, A, B, C, D;
  int     res;

  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

  /* init temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, 
                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x = a, y = b */
  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
      goto LBL_ERR;
  }
  if ((res = mp_copy (b, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 2. [modified] if x,y are both even then return an error! */
  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&A, 1);
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if A or B is odd then */
    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
      /* A = (A+y)/2, B = (B-x)/2 */
      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* A = A/2, B = B/2 */
    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if C or D is odd then */
    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
      /* C = (C+y)/2, D = (D-x)/2 */
      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* C = C/2, D = D/2 */
    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, A = A - C, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, C = C - A, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0)
    goto top;

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* if its too low */
  while (mp_cmp_d(&C, 0) == MP_LT) {
      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* too big */
  while (mp_cmp_mag(&C, b) != MP_LT) {
      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* C is now the inverse */
  mp_exch (&C, c);
  res = MP_OKAY;
LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
  return res;
}
#endif

/* End: bn_mp_invmod_slow.c */

/* Start: bn_mp_is_square.c */
#include <tommath.h>
#ifdef BN_MP_IS_SQUARE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Check if remainders are possible squares - fast exclude non-squares */
static const char rem_128[128] = {
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
};

static const char rem_105[105] = {
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
};

/* Store non-zero to ret if arg is square, and zero if not */
int mp_is_square(mp_int *arg,int *ret) 
{
  int           res;
  mp_digit      c;
  mp_int        t;
  unsigned long r;

  /* Default to Non-square :) */
  *ret = MP_NO; 

  if (arg->sign == MP_NEG) {
    return MP_VAL;
  }

  /* digits used?  (TSD) */
  if (arg->used == 0) {
     return MP_OKAY;
  }

  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
  if (rem_128[127 & DIGIT(arg,0)] == 1) {
     return MP_OKAY;
  }

  /* Next check mod 105 (3*5*7) */
  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
     return res;
  }
  if (rem_105[c] == 1) {
     return MP_OKAY;
  }


  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
     return res;
  }
  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
     goto ERR;
  }
  r = mp_get_int(&t);
  /* Check for other prime modules, note it's not an ERROR but we must
   * free "t" so the easiest way is to goto ERR.  We know that res
   * is already equal to MP_OKAY from the mp_mod call 
   */ 
  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;

  /* Final check - is sqr(sqrt(arg)) == arg ? */
  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
     goto ERR;
  }
  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
     goto ERR;
  }

  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
ERR:mp_clear(&t);
  return res;
}
#endif

/* End: bn_mp_is_square.c */

/* Start: bn_mp_jacobi.c */
#include <tommath.h>
#ifdef BN_MP_JACOBI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes the jacobi c = (a | n) (or Legendre if n is prime)
 * HAC pp. 73 Algorithm 2.149
 */
int mp_jacobi (mp_int * a, mp_int * p, int *c)
{
  mp_int  a1, p1;
  int     k, s, r, res;
  mp_digit residue;

  /* if p <= 0 return MP_VAL */
  if (mp_cmp_d(p, 0) != MP_GT) {
     return MP_VAL;
  }

  /* step 1.  if a == 0, return 0 */
  if (mp_iszero (a) == 1) {
    *c = 0;
    return MP_OKAY;
  }

  /* step 2.  if a == 1, return 1 */
  if (mp_cmp_d (a, 1) == MP_EQ) {
    *c = 1;
    return MP_OKAY;
  }

  /* default */
  s = 0;

  /* step 3.  write a = a1 * 2**k  */
  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&p1)) != MP_OKAY) {
    goto LBL_A1;
  }

  /* divide out larger power of two */
  k = mp_cnt_lsb(&a1);
  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
     goto LBL_P1;
  }

  /* step 4.  if e is even set s=1 */
  if ((k & 1) == 0) {
    s = 1;
  } else {
    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
    residue = p->dp[0] & 7;

    if (residue == 1 || residue == 7) {
      s = 1;
    } else if (residue == 3 || residue == 5) {
      s = -1;
    }
  }

  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
    s = -s;
  }

  /* if a1 == 1 we're done */
  if (mp_cmp_d (&a1, 1) == MP_EQ) {
    *c = s;
  } else {
    /* n1 = n mod a1 */
    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
      goto LBL_P1;
    }
    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
      goto LBL_P1;
    }
    *c = s * r;
  }

  /* done */
  res = MP_OKAY;
LBL_P1:mp_clear (&p1);
LBL_A1:mp_clear (&a1);
  return res;
}
#endif

/* End: bn_mp_jacobi.c */

/* Start: bn_mp_karatsuba_mul.c */
#include <tommath.h>
#ifdef BN_MP_KARATSUBA_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* c = |a| * |b| using Karatsuba Multiplication using 
 * three half size multiplications
 *
 * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
 * let n represent half of the number of digits in 
 * the min(a,b)
 *
 * a = a1 * B**n + a0
 * b = b1 * B**n + b0
 *
 * Then, a * b => 
   a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
 *
 * Note that a1b1 and a0b0 are used twice and only need to be 
 * computed once.  So in total three half size (half # of 
 * digit) multiplications are performed, a0b0, a1b1 and 
 * (a1+b1)(a0+b0)
 *
 * Note that a multiplication of half the digits requires
 * 1/4th the number of single precision multiplications so in 
 * total after one call 25% of the single precision multiplications 
 * are saved.  Note also that the call to mp_mul can end up back 
 * in this function if the a0, a1, b0, or b1 are above the threshold.  
 * This is known as divide-and-conquer and leads to the famous 
 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
 * the standard O(N**2) that the baseline/comba methods use.  
 * Generally though the overhead of this method doesn't pay off 
 * until a certain size (N ~ 80) is reached.
 */
int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
  int     B, err;

  /* default the return code to an error */
  err = MP_MEM;

  /* min # of digits */
  B = MIN (a->used, b->used);

  /* now divide in two */
  B = B >> 1;

  /* init copy all the temps */
  if (mp_init_size (&x0, B) != MP_OKAY)
    goto ERR;
  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
    goto X0;
  if (mp_init_size (&y0, B) != MP_OKAY)
    goto X1;
  if (mp_init_size (&y1, b->used - B) != MP_OKAY)
    goto Y0;

  /* init temps */
  if (mp_init_size (&t1, B * 2) != MP_OKAY)
    goto Y1;
  if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
    goto T1;
  if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
    goto X0Y0;

  /* now shift the digits */
  x0.used = y0.used = B;
  x1.used = a->used - B;
  y1.used = b->used - B;

  {
    register int x;
    register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;

    /* we copy the digits directly instead of using higher level functions
     * since we also need to shift the digits
     */
    tmpa = a->dp;
    tmpb = b->dp;

    tmpx = x0.dp;
    tmpy = y0.dp;
    for (x = 0; x < B; x++) {
      *tmpx++ = *tmpa++;
      *tmpy++ = *tmpb++;
    }

    tmpx = x1.dp;
    for (x = B; x < a->used; x++) {
      *tmpx++ = *tmpa++;
    }

    tmpy = y1.dp;
    for (x = B; x < b->used; x++) {
      *tmpy++ = *tmpb++;
    }
  }

  /* only need to clamp the lower words since by definition the 
   * upper words x1/y1 must have a known number of digits
   */
  mp_clamp (&x0);
  mp_clamp (&y0);

  /* now calc the products x0y0 and x1y1 */
  /* after this x0 is no longer required, free temp [x0==t2]! */
  if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
    goto X1Y1;          /* x0y0 = x0*y0 */
  if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
    goto X1Y1;          /* x1y1 = x1*y1 */

  /* now calc x1+x0 and y1+y0 */
  if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = x1 - x0 */
  if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
    goto X1Y1;          /* t2 = y1 - y0 */
  if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = (x1 + x0) * (y1 + y0) */

  /* add x0y0 */
  if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
    goto X1Y1;          /* t2 = x0y0 + x1y1 */
  if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */

  /* shift by B */
  if (mp_lshd (&t1, B) != MP_OKAY)
    goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
    goto X1Y1;          /* x1y1 = x1y1 << 2*B */

  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = x0y0 + t1 */
  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */

  /* Algorithm succeeded set the return code to MP_OKAY */
  err = MP_OKAY;

X1Y1:mp_clear (&x1y1);
X0Y0:mp_clear (&x0y0);
T1:mp_clear (&t1);
Y1:mp_clear (&y1);
Y0:mp_clear (&y0);
X1:mp_clear (&x1);
X0:mp_clear (&x0);
ERR:
  return err;
}
#endif

/* End: bn_mp_karatsuba_mul.c */

/* Start: bn_mp_karatsuba_sqr.c */
#include <tommath.h>
#ifdef BN_MP_KARATSUBA_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Karatsuba squaring, computes b = a*a using three 
 * half size squarings
 *
 * See comments of karatsuba_mul for details.  It 
 * is essentially the same algorithm but merely 
 * tuned to perform recursive squarings.
 */
int mp_karatsuba_sqr (mp_int * a, mp_int * b)
{
  mp_int  x0, x1, t1, t2, x0x0, x1x1;
  int     B, err;

  err = MP_MEM;

  /* min # of digits */
  B = a->used;

  /* now divide in two */
  B = B >> 1;

  /* init copy all the temps */
  if (mp_init_size (&x0, B) != MP_OKAY)
    goto ERR;
  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
    goto X0;

  /* init temps */
  if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
    goto X1;
  if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
    goto T1;
  if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
    goto T2;
  if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
    goto X0X0;

  {
    register int x;
    register mp_digit *dst, *src;

    src = a->dp;

    /* now shift the digits */
    dst = x0.dp;
    for (x = 0; x < B; x++) {
      *dst++ = *src++;
    }

    dst = x1.dp;
    for (x = B; x < a->used; x++) {
      *dst++ = *src++;
    }
  }

  x0.used = B;
  x1.used = a->used - B;

  mp_clamp (&x0);

  /* now calc the products x0*x0 and x1*x1 */
  if (mp_sqr (&x0, &x0x0) != MP_OKAY)
    goto X1X1;           /* x0x0 = x0*x0 */
  if (mp_sqr (&x1, &x1x1) != MP_OKAY)
    goto X1X1;           /* x1x1 = x1*x1 */

  /* now calc (x1+x0)**2 */
  if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = x1 - x0 */
  if (mp_sqr (&t1, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */

  /* add x0y0 */
  if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
    goto X1X1;           /* t2 = x0x0 + x1x1 */
  if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */

  /* shift by B */
  if (mp_lshd (&t1, B) != MP_OKAY)
    goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
    goto X1X1;           /* x1x1 = x1x1 << 2*B */

  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = x0x0 + t1 */
  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */

  err = MP_OKAY;

X1X1:mp_clear (&x1x1);
X0X0:mp_clear (&x0x0);
T2:mp_clear (&t2);
T1:mp_clear (&t1);
X1:mp_clear (&x1);
X0:mp_clear (&x0);
ERR:
  return err;
}
#endif

/* End: bn_mp_karatsuba_sqr.c */

/* Start: bn_mp_lcm.c */
#include <tommath.h>
#ifdef BN_MP_LCM_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes least common multiple as |a*b|/(a, b) */
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
{
  int     res;
  mp_int  t1, t2;


  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
    return res;
  }

  /* t1 = get the GCD of the two inputs */
  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
    goto LBL_T;
  }

  /* divide the smallest by the GCD */
  if (mp_cmp_mag(a, b) == MP_LT) {
     /* store quotient in t2 such that t2 * b is the LCM */
     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
        goto LBL_T;
     }
     res = mp_mul(b, &t2, c);
  } else {
     /* store quotient in t2 such that t2 * a is the LCM */
     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
        goto LBL_T;
     }
     res = mp_mul(a, &t2, c);
  }

  /* fix the sign to positive */
  c->sign = MP_ZPOS;

LBL_T:
  mp_clear_multi (&t1, &t2, NULL);
  return res;
}
#endif

/* End: bn_mp_lcm.c */

/* Start: bn_mp_lshd.c */
#include <tommath.h>
#ifdef BN_MP_LSHD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* shift left a certain amount of digits */
int mp_lshd (mp_int * a, int b)
{
  int     x, res;

  /* if its less than zero return */
  if (b <= 0) {
    return MP_OKAY;
  }

  /* grow to fit the new digits */
  if (a->alloc < a->used + b) {
     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
       return res;
     }
  }

  {
    register mp_digit *top, *bottom;

    /* increment the used by the shift amount then copy upwards */
    a->used += b;

    /* top */
    top = a->dp + a->used - 1;

    /* base */
    bottom = a->dp + a->used - 1 - b;

    /* much like mp_rshd this is implemented using a sliding window
     * except the window goes the otherway around.  Copying from
     * the bottom to the top.  see bn_mp_rshd.c for more info.
     */
    for (x = a->used - 1; x >= b; x--) {
      *top-- = *bottom--;
    }

    /* zero the lower digits */
    top = a->dp;
    for (x = 0; x < b; x++) {
      *top++ = 0;
    }
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_lshd.c */

/* Start: bn_mp_mod.c */
#include <tommath.h>
#ifdef BN_MP_MOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* c = a mod b, 0 <= c < b */
int
mp_mod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  t;
  int     res;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }

  if (t.sign != b->sign) {
    res = mp_add (b, &t, c);
  } else {
    res = MP_OKAY;
    mp_exch (&t, c);
  }

  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_mod.c */

/* Start: bn_mp_mod_2d.c */
#include <tommath.h>
#ifdef BN_MP_MOD_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* calc a value mod 2**b */
int
mp_mod_2d (mp_int * a, int b, mp_int * c)
{
  int     x, res;

  /* if b is <= 0 then zero the int */
  if (b <= 0) {
    mp_zero (c);
    return MP_OKAY;
  }

  /* if the modulus is larger than the value than return */
  if (b >= (int) (a->used * DIGIT_BIT)) {
    res = mp_copy (a, c);
    return res;
  }

  /* copy */
  if ((res = mp_copy (a, c)) != MP_OKAY) {
    return res;
  }

  /* zero digits above the last digit of the modulus */
  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
    c->dp[x] = 0;
  }
  /* clear the digit that is not completely outside/inside the modulus */
  c->dp[b / DIGIT_BIT] &=
    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_mp_mod_2d.c */

/* Start: bn_mp_mod_d.c */
#include <tommath.h>
#ifdef BN_MP_MOD_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

int
mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
{
  return mp_div_d(a, b, NULL, c);
}
#endif

/* End: bn_mp_mod_d.c */

/* Start: bn_mp_montgomery_calc_normalization.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/*
 * shifts with subtractions when the result is greater than b.
 *
 * The method is slightly modified to shift B unconditionally upto just under
 * the leading bit of b.  This saves alot of multiple precision shifting.
 */
int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
{
  int     x, bits, res;

  /* how many bits of last digit does b use */
  bits = mp_count_bits (b) % DIGIT_BIT;

  if (b->used > 1) {
     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
        return res;
     }
  } else {
     mp_set(a, 1);
     bits = 1;
  }


  /* now compute C = A * B mod b */
  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
      return res;
    }
    if (mp_cmp_mag (a, b) != MP_LT) {
      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
        return res;
      }
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_calc_normalization.c */

/* Start: bn_mp_montgomery_reduce.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes xR**-1 == x (mod N) via Montgomery Reduction */
int
mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
{
  int     ix, res, digs;
  mp_digit mu;

  /* can the fast reduction [comba] method be used?
   *
   * Note that unlike in mul you're safely allowed *less*
   * than the available columns [255 per default] since carries
   * are fixed up in the inner loop.
   */
  digs = n->used * 2 + 1;
  if ((digs < MP_WARRAY) &&
      n->used <
      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_mp_montgomery_reduce (x, n, rho);
  }

  /* grow the input as required */
  if (x->alloc < digs) {
    if ((res = mp_grow (x, digs)) != MP_OKAY) {
      return res;
    }
  }
  x->used = digs;

  for (ix = 0; ix < n->used; ix++) {
    /* mu = ai * rho mod b
     *
     * The value of rho must be precalculated via
     * montgomery_setup() such that
     * it equals -1/n0 mod b this allows the
     * following inner loop to reduce the
     * input one digit at a time
     */
    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);

    /* a = a + mu * m * b**i */
    {
      register int iy;
      register mp_digit *tmpn, *tmpx, u;
      register mp_word r;

      /* alias for digits of the modulus */
      tmpn = n->dp;

      /* alias for the digits of x [the input] */
      tmpx = x->dp + ix;

      /* set the carry to zero */
      u = 0;

      /* Multiply and add in place */
      for (iy = 0; iy < n->used; iy++) {
        /* compute product and sum */
        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
                  ((mp_word) u) + ((mp_word) * tmpx);

        /* get carry */
        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));

        /* fix digit */
        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
      }
      /* At this point the ix'th digit of x should be zero */


      /* propagate carries upwards as required*/
      while (u) {
        *tmpx   += u;
        u        = *tmpx >> DIGIT_BIT;
        *tmpx++ &= MP_MASK;
      }
    }
  }

  /* at this point the n.used'th least
   * significant digits of x are all zero
   * which means we can shift x to the
   * right by n.used digits and the
   * residue is unchanged.
   */

  /* x = x/b**n.used */
  mp_clamp(x);
  mp_rshd (x, n->used);

  /* if x >= n then x = x - n */
  if (mp_cmp_mag (x, n) != MP_LT) {
    return s_mp_sub (x, n, x);
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_reduce.c */

/* Start: bn_mp_montgomery_setup.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* setups the montgomery reduction stuff */
int
mp_montgomery_setup (mp_int * n, mp_digit * rho)
{
  mp_digit x, b;

/* fast inversion mod 2**k
 *
 * Based on the fact that
 *
 * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
 *                    =>  2*X*A - X*X*A*A = 1
 *                    =>  2*(1) - (1)     = 1
 */
  b = n->dp[0];

  if ((b & 1) == 0) {
    return MP_VAL;
  }

  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
#if !defined(MP_8BIT)
  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
#endif
#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
#endif
#ifdef MP_64BIT
  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
#endif

  /* rho = -1/m mod b */
  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_setup.c */

/* Start: bn_mp_mul.c */
#include <tommath.h>
#ifdef BN_MP_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* high level multiplication (handles sign) */
int mp_mul (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, neg;
  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;

  /* use Toom-Cook? */
#ifdef BN_MP_TOOM_MUL_C
  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
    res = mp_toom_mul(a, b, c);
  } else 
#endif
#ifdef BN_MP_KARATSUBA_MUL_C
  /* use Karatsuba? */
  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
    res = mp_karatsuba_mul (a, b, c);
  } else 
#endif
  {
    /* can we use the fast multiplier?
     *
     * The fast multiplier can be used if the output will 
     * have less than MP_WARRAY digits and the number of 
     * digits won't affect carry propagation
     */
    int     digs = a->used + b->used + 1;

#ifdef BN_FAST_S_MP_MUL_DIGS_C
    if ((digs < MP_WARRAY) &&
        MIN(a->used, b->used) <= 
        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
      res = fast_s_mp_mul_digs (a, b, c, digs);
    } else 
#endif
#ifdef BN_S_MP_MUL_DIGS_C
      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
#else
      res = MP_VAL;
#endif

  }
  c->sign = (c->used > 0) ? neg : MP_ZPOS;
  return res;
}
#endif

/* End: bn_mp_mul.c */

/* Start: bn_mp_mul_2.c */
#include <tommath.h>
#ifdef BN_MP_MUL_2_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* b = a*2 */
int mp_mul_2(mp_int * a, mp_int * b)
{
  int     x, res, oldused;

  /* grow to accomodate result */
  if (b->alloc < a->used + 1) {
    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  oldused = b->used;
  b->used = a->used;

  {
    register mp_digit r, rr, *tmpa, *tmpb;

    /* alias for source */
    tmpa = a->dp;
    
    /* alias for dest */
    tmpb = b->dp;

    /* carry */
    r = 0;
    for (x = 0; x < a->used; x++) {
    
      /* get what will be the *next* carry bit from the 
       * MSB of the current digit 
       */
      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
      
      /* now shift up this digit, add in the carry [from the previous] */
      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
      
      /* copy the carry that would be from the source 
       * digit into the next iteration 
       */
      r = rr;
    }

    /* new leading digit? */
    if (r != 0) {
      /* add a MSB which is always 1 at this point */
      *tmpb = 1;
      ++(b->used);
    }

    /* now zero any excess digits on the destination 
     * that we didn't write to 
     */
    tmpb = b->dp + b->used;
    for (x = b->used; x < oldused; x++) {
      *tmpb++ = 0;
    }
  }
  b->sign = a->sign;
  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_2.c */

/* Start: bn_mp_mul_2d.c */
#include <tommath.h>
#ifdef BN_MP_MUL_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* shift left by a certain bit count */
int mp_mul_2d (mp_int * a, int b, mp_int * c)
{
  mp_digit d;
  int      res;

  /* copy */
  if (a != c) {
     if ((res = mp_copy (a, c)) != MP_OKAY) {
       return res;
     }
  }

  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
       return res;
     }
  }

  /* shift by as many digits in the bit count */
  if (b >= (int)DIGIT_BIT) {
    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
      return res;
    }
  }

  /* shift any bit count < DIGIT_BIT */
  d = (mp_digit) (b % DIGIT_BIT);
  if (d != 0) {
    register mp_digit *tmpc, shift, mask, r, rr;
    register int x;

    /* bitmask for carries */
    mask = (((mp_digit)1) << d) - 1;

    /* shift for msbs */
    shift = DIGIT_BIT - d;

    /* alias */
    tmpc = c->dp;

    /* carry */
    r    = 0;
    for (x = 0; x < c->used; x++) {
      /* get the higher bits of the current word */
      rr = (*tmpc >> shift) & mask;

      /* shift the current word and OR in the carry */
      *tmpc = ((*tmpc << d) | r) & MP_MASK;
      ++tmpc;

      /* set the carry to the carry bits of the current word */
      r = rr;
    }
    
    /* set final carry */
    if (r != 0) {
       c->dp[(c->used)++] = r;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_2d.c */

/* Start: bn_mp_mul_d.c */
#include <tommath.h>
#ifdef BN_MP_MUL_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* multiply by a digit */
int
mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
{
  mp_digit u, *tmpa, *tmpc;
  mp_word  r;
  int      ix, res, olduse;

  /* make sure c is big enough to hold a*b */
  if (c->alloc < a->used + 1) {
    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* get the original destinations used count */
  olduse = c->used;

  /* set the sign */
  c->sign = a->sign;

  /* alias for a->dp [source] */
  tmpa = a->dp;

  /* alias for c->dp [dest] */
  tmpc = c->dp;

  /* zero carry */
  u = 0;

  /* compute columns */
  for (ix = 0; ix < a->used; ix++) {
    /* compute product and carry sum for this term */
    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);

    /* mask off higher bits to get a single digit */
    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));

    /* send carry into next iteration */
    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  }

  /* store final carry [if any] and increment ix offset  */
  *tmpc++ = u;
  ++ix;

  /* now zero digits above the top */
  while (ix++ < olduse) {
     *tmpc++ = 0;
  }

  /* set used count */
  c->used = a->used + 1;
  mp_clamp(c);

  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_d.c */

/* Start: bn_mp_mulmod.c */
#include <tommath.h>
#ifdef BN_MP_MULMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* d = a * b (mod c) */
int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_mulmod.c */

/* Start: bn_mp_n_root.c */
#include <tommath.h>
#ifdef BN_MP_N_ROOT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* find the n'th root of an integer 
 *
 * Result found such that (c)**b <= a and (c+1)**b > a 
 *
 * This algorithm uses Newton's approximation 
 * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
 * which will find the root in log(N) time where 
 * each step involves a fair bit.  This is not meant to 
 * find huge roots [square and cube, etc].
 */
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{
  mp_int  t1, t2, t3;
  int     res, neg;

  /* input must be positive if b is even */
  if ((b & 1) == 0 && a->sign == MP_NEG) {
    return MP_VAL;
  }

  if ((res = mp_init (&t1)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init (&t3)) != MP_OKAY) {
    goto LBL_T2;
  }

  /* if a is negative fudge the sign but keep track */
  neg     = a->sign;
  a->sign = MP_ZPOS;

  /* t2 = 2 */
  mp_set (&t2, 2);

  do {
    /* t1 = t2 */
    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
    
    /* t3 = t1**(b-1) */
    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
      goto LBL_T3;
    }

    /* numerator */
    /* t2 = t1**b */
    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t2 = t1**b - a */
    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
      goto LBL_T3;
    }

    /* denominator */
    /* t3 = t1**(b-1) * b  */
    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
      goto LBL_T3;
    }

    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }
  }  while (mp_cmp (&t1, &t2) != MP_EQ);

  /* result can be off by a few so check */
  for (;;) {
    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    if (mp_cmp (&t2, a) == MP_GT) {
      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
         goto LBL_T3;
      }
    } else {
      break;
    }
  }

  /* reset the sign of a first */
  a->sign = neg;

  /* set the result */
  mp_exch (&t1, c);

  /* set the sign of the result */
  c->sign = neg;

  res = MP_OKAY;

LBL_T3:mp_clear (&t3);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
  return res;
}
#endif

/* End: bn_mp_n_root.c */

/* Start: bn_mp_neg.c */
#include <tommath.h>
#ifdef BN_MP_NEG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* b = -a */
int mp_neg (mp_int * a, mp_int * b)
{
  int     res;
  if (a != b) {
     if ((res = mp_copy (a, b)) != MP_OKAY) {
        return res;
     }
  }

  if (mp_iszero(b) != MP_YES) {
     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
  } else {
     b->sign = MP_ZPOS;
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_neg.c */

/* Start: bn_mp_or.c */
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* OR two ints together */
int mp_or (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] |= x->dp[ix];
  }
  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_or.c */

/* Start: bn_mp_prime_fermat.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_FERMAT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* performs one Fermat test.
 * 
 * If "a" were prime then b**a == b (mod a) since the order of
 * the multiplicative sub-group would be phi(a) = a-1.  That means
 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
 *
 * Sets result to 1 if the congruence holds, or zero otherwise.
 */
int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
{
  mp_int  t;
  int     err;

  /* default to composite  */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }

  /* init t */
  if ((err = mp_init (&t)) != MP_OKAY) {
    return err;
  }

  /* compute t = b**a mod a */
  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
    goto LBL_T;
  }

  /* is it equal to b? */
  if (mp_cmp (&t, b) == MP_EQ) {
    *result = MP_YES;
  }

  err = MP_OKAY;
LBL_T:mp_clear (&t);
  return err;
}
#endif

/* End: bn_mp_prime_fermat.c */

/* Start: bn_mp_prime_is_divisible.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines if an integers is divisible by one 
 * of the first PRIME_SIZE primes or not
 *
 * sets result to 0 if not, 1 if yes
 */
int mp_prime_is_divisible (mp_int * a, int *result)
{
  int     err, ix;
  mp_digit res;

  /* default to not */
  *result = MP_NO;

  for (ix = 0; ix < PRIME_SIZE; ix++) {
    /* what is a mod LBL_prime_tab[ix] */
    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
      return err;
    }

    /* is the residue zero? */
    if (res == 0) {
      *result = MP_YES;
      return MP_OKAY;
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_prime_is_divisible.c */

/* Start: bn_mp_prime_is_prime.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_IS_PRIME_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* performs a variable number of rounds of Miller-Rabin
 *
 * Probability of error after t rounds is no more than

 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
int mp_prime_is_prime (mp_int * a, int t, int *result)
{
  mp_int  b;
  int     ix, err, res;

  /* default to no */
  *result = MP_NO;

  /* valid value of t? */
  if (t <= 0 || t > PRIME_SIZE) {
    return MP_VAL;
  }

  /* is the input equal to one of the primes in the table? */
  for (ix = 0; ix < PRIME_SIZE; ix++) {
      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
         *result = 1;
         return MP_OKAY;
      }
  }

  /* first perform trial division */
  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
    return err;
  }

  /* return if it was trivially divisible */
  if (res == MP_YES) {
    return MP_OKAY;
  }

  /* now perform the miller-rabin rounds */
  if ((err = mp_init (&b)) != MP_OKAY) {
    return err;
  }

  for (ix = 0; ix < t; ix++) {
    /* set the prime */
    mp_set (&b, ltm_prime_tab[ix]);

    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
      goto LBL_B;
    }

    if (res == MP_NO) {
      goto LBL_B;
    }
  }

  /* passed the test */
  *result = MP_YES;
LBL_B:mp_clear (&b);
  return err;
}
#endif

/* End: bn_mp_prime_is_prime.c */

/* Start: bn_mp_prime_miller_rabin.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_MILLER_RABIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Miller-Rabin test of "a" to the base of "b" as described in 
 * HAC pp. 139 Algorithm 4.24
 *
 * Sets result to 0 if definitely composite or 1 if probably prime.
 * Randomly the chance of error is no more than 1/4 and often 
 * very much lower.
 */
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{
  mp_int  n1, y, r;
  int     s, j, err;

  /* default */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }     

  /* get n1 = a - 1 */
  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
    return err;
  }
  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* set 2**s * r = n1 */
  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* count the number of least significant bits
   * which are zero
   */
  s = mp_cnt_lsb(&r);

  /* now divide n - 1 by 2**s */
  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
    goto LBL_R;
  }

  /* compute y = b**r mod a */
  if ((err = mp_init (&y)) != MP_OKAY) {
    goto LBL_R;
  }
  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
    goto LBL_Y;
  }

  /* if y != 1 and y != n1 do */
  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
    j = 1;
    /* while j <= s-1 and y != n1 */
    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
         goto LBL_Y;
      }

      /* if y == 1 then composite */
      if (mp_cmp_d (&y, 1) == MP_EQ) {
         goto LBL_Y;
      }

      ++j;
    }

    /* if y != n1 then composite */
    if (mp_cmp (&y, &n1) != MP_EQ) {
      goto LBL_Y;
    }
  }

  /* probably prime now */
  *result = MP_YES;
LBL_Y:mp_clear (&y);
LBL_R:mp_clear (&r);
LBL_N1:mp_clear (&n1);
  return err;
}
#endif

/* End: bn_mp_prime_miller_rabin.c */

/* Start: bn_mp_prime_next_prime.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_NEXT_PRIME_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
{
   int      err, res, x, y;
   mp_digit res_tab[PRIME_SIZE], step, kstep;
   mp_int   b;

   /* ensure t is valid */
   if (t <= 0 || t > PRIME_SIZE) {
      return MP_VAL;
   }

   /* force positive */
   a->sign = MP_ZPOS;

   /* simple algo if a is less than the largest prime in the table */
   if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
      /* find which prime it is bigger than */
      for (x = PRIME_SIZE - 2; x >= 0; x--) {
          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
             if (bbs_style == 1) {
                /* ok we found a prime smaller or
                 * equal [so the next is larger]
                 *
                 * however, the prime must be
                 * congruent to 3 mod 4
                 */
                if ((ltm_prime_tab[x + 1] & 3) != 3) {
                   /* scan upwards for a prime congruent to 3 mod 4 */
                   for (y = x + 1; y < PRIME_SIZE; y++) {
                       if ((ltm_prime_tab[y] & 3) == 3) {
                          mp_set(a, ltm_prime_tab[y]);
                          return MP_OKAY;
                       }
                   }
                }
             } else {
                mp_set(a, ltm_prime_tab[x + 1]);
                return MP_OKAY;
             }
          }
      }
      /* at this point a maybe 1 */
      if (mp_cmp_d(a, 1) == MP_EQ) {
         mp_set(a, 2);
         return MP_OKAY;
      }
      /* fall through to the sieve */
   }

   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
   if (bbs_style == 1) {
      kstep   = 4;
   } else {
      kstep   = 2;
   }

   /* at this point we will use a combination of a sieve and Miller-Rabin */

   if (bbs_style == 1) {
      /* if a mod 4 != 3 subtract the correct value to make it so */
      if ((a->dp[0] & 3) != 3) {
         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
      }
   } else {
      if (mp_iseven(a) == 1) {
         /* force odd */
         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
            return err;
         }
      }
   }

   /* generate the restable */
   for (x = 1; x < PRIME_SIZE; x++) {
      if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
         return err;
      }
   }

   /* init temp used for Miller-Rabin Testing */
   if ((err = mp_init(&b)) != MP_OKAY) {
      return err;
   }

   for (;;) {
      /* skip to the next non-trivially divisible candidate */
      step = 0;
      do {
         /* y == 1 if any residue was zero [e.g. cannot be prime] */
         y     =  0;

         /* increase step to next candidate */
         step += kstep;

         /* compute the new residue without using division */
         for (x = 1; x < PRIME_SIZE; x++) {
             /* add the step to each residue */
             res_tab[x] += kstep;

             /* subtract the modulus [instead of using division] */
             if (res_tab[x] >= ltm_prime_tab[x]) {
                res_tab[x]  -= ltm_prime_tab[x];
             }

             /* set flag if zero */
             if (res_tab[x] == 0) {
                y = 1;
             }
         }
      } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));

      /* add the step */
      if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
         goto LBL_ERR;
      }

      /* if didn't pass sieve and step == MAX then skip test */
      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
         continue;
      }

      /* is this prime? */
      for (x = 0; x < t; x++) {
          mp_set(&b, ltm_prime_tab[x]);
          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
             goto LBL_ERR;
          }
          if (res == MP_NO) {
             break;
          }
      }

      if (res == MP_YES) {
         break;
      }
   }

   err = MP_OKAY;
LBL_ERR:
   mp_clear(&b);
   return err;
}

#endif

/* End: bn_mp_prime_next_prime.c */

/* Start: bn_mp_prime_rabin_miller_trials.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */


static const struct {
   int k, t;
} sizes[] = {
{   128,    28 },
{   256,    16 },
{   384,    10 },
{   512,     7 },
{   640,     6 },
{   768,     5 },
{   896,     4 },
{  1024,     4 }
};

/* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size)
{
   int x;

   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
       if (sizes[x].k == size) {
          return sizes[x].t;
       } else if (sizes[x].k > size) {
          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
       }
   }
   return sizes[x-1].t + 1;
}


#endif

/* End: bn_mp_prime_rabin_miller_trials.c */

/* Start: bn_mp_prime_random_ex.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_RANDOM_EX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */

/* This is possibly the mother of all prime generation functions, muahahahahaha! */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
{
   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
   int res, err, bsize, maskOR_msb_offset;

   /* sanity check the input */
   if (size <= 1 || t <= 0) {
      return MP_VAL;
   }

   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
   if (flags & LTM_PRIME_SAFE) {
      flags |= LTM_PRIME_BBS;
   }

   /* calc the byte size */
   bsize = (size>>3) + ((size&7)?1:0);

   /* we need a buffer of bsize bytes */
   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
   if (tmp == NULL) {
      return MP_MEM;
   }

   /* calc the maskAND value for the MSbyte*/
   maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));

   /* calc the maskOR_msb */
   maskOR_msb        = 0;
   maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
   if (flags & LTM_PRIME_2MSB_ON) {
      maskOR_msb       |= 0x80 >> ((9 - size) & 7);
   }  

   /* get the maskOR_lsb */
   maskOR_lsb         = 1;
   if (flags & LTM_PRIME_BBS) {
      maskOR_lsb     |= 3;
   }

   do {
      /* read the bytes */
      if (cb(tmp, bsize, dat) != bsize) {
         err = MP_VAL;
         goto error;
      }
 
      /* work over the MSbyte */
      tmp[0]    &= maskAND;
      tmp[0]    |= 1 << ((size - 1) & 7);

      /* mix in the maskORs */
      tmp[maskOR_msb_offset]   |= maskOR_msb;
      tmp[bsize-1]             |= maskOR_lsb;

      /* read it in */
      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }

      /* is it prime? */
      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
      if (res == MP_NO) {  
         continue;
      }

      if (flags & LTM_PRIME_SAFE) {
         /* see if (a-1)/2 is prime */
         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
 
         /* is it prime? */
         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
      }
   } while (res == MP_NO);

   if (flags & LTM_PRIME_SAFE) {
      /* restore a to the original value */
      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
   }

   err = MP_OKAY;
error:
   XFREE(tmp);
   return err;
}


#endif

/* End: bn_mp_prime_random_ex.c */

/* Start: bn_mp_radix_size.c */
#include <tommath.h>
#ifdef BN_MP_RADIX_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* returns size of ASCII reprensentation */
int mp_radix_size (mp_int * a, int radix, int *size)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;

  *size = 0;

  /* special case for binary */
  if (radix == 2) {
    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
    return MP_OKAY;
  }

  /* make sure the radix is in range */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  if (mp_iszero(a) == MP_YES) {
    *size = 2;
    return MP_OKAY;
  }

  /* digs is the digit count */
  digs = 0;

  /* if it's negative add one for the sign */
  if (a->sign == MP_NEG) {
    ++digs;
  }

  /* init a copy of the input */
  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* force temp to positive */
  t.sign = MP_ZPOS; 

  /* fetch out all of the digits */
  while (mp_iszero (&t) == MP_NO) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    ++digs;
  }
  mp_clear (&t);

  /* return digs + 1, the 1 is for the NULL byte that would be required. */
  *size = digs + 1;
  return MP_OKAY;
}

#endif

/* End: bn_mp_radix_size.c */

/* Start: bn_mp_radix_smap.c */
#include <tommath.h>
#ifdef BN_MP_RADIX_SMAP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* chars used in radix conversions */
const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
#endif

/* End: bn_mp_radix_smap.c */

/* Start: bn_mp_rand.c */
#include <tommath.h>
#ifdef BN_MP_RAND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* makes a pseudo-random int of a given size */
int
mp_rand (mp_int * a, int digits)
{
  int     res;
  mp_digit d;

  mp_zero (a);
  if (digits <= 0) {
    return MP_OKAY;
  }

  /* first place a random non-zero digit */
  do {
    d = ((mp_digit) abs (rand ())) & MP_MASK;
  } while (d == 0);

  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
    return res;
  }

  while (--digits > 0) {
    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
      return res;
    }

    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
      return res;
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_rand.c */

/* Start: bn_mp_read_radix.c */
#include <tommath.h>
#ifdef BN_MP_READ_RADIX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* read a string [ASCII] in a given radix */
int mp_read_radix (mp_int * a, const char *str, int radix)
{
  int     y, res, neg;
  char    ch;

  /* zero the digit bignum */
  mp_zero(a);

  /* make sure the radix is ok */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* if the leading digit is a 
   * minus set the sign to negative. 
   */
  if (*str == '-') {
    ++str;
    neg = MP_NEG;
  } else {
    neg = MP_ZPOS;
  }

  /* set the integer to the default of zero */
  mp_zero (a);
  
  /* process each digit of the string */
  while (*str) {
    /* if the radix < 36 the conversion is case insensitive
     * this allows numbers like 1AB and 1ab to represent the same  value
     * [e.g. in hex]
     */
    ch = (char) ((radix < 36) ? toupper (*str) : *str);
    for (y = 0; y < 64; y++) {
      if (ch == mp_s_rmap[y]) {
         break;
      }
    }

    /* if the char was found in the map 
     * and is less than the given radix add it
     * to the number, otherwise exit the loop. 
     */
    if (y < radix) {
      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
         return res;
      }
      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
         return res;
      }
    } else {
      break;
    }
    ++str;
  }
  
  /* set the sign only if a != 0 */
  if (mp_iszero(a) != 1) {
     a->sign = neg;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_read_radix.c */

/* Start: bn_mp_read_signed_bin.c */
#include <tommath.h>
#ifdef BN_MP_READ_SIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* read signed bin, big endian, first byte is 0==positive or 1==negative */
int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c)
{
  int     res;

  /* read magnitude */
  if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
    return res;
  }

  /* first byte is 0 for positive, non-zero for negative */
  if (b[0] == 0) {
     a->sign = MP_ZPOS;
  } else {
     a->sign = MP_NEG;
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_read_signed_bin.c */

/* Start: bn_mp_read_unsigned_bin.c */
#include <tommath.h>
#ifdef BN_MP_READ_UNSIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reads a unsigned char array, assumes the msb is stored first [big endian] */
int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
{
  int     res;

  /* make sure there are at least two digits */
  if (a->alloc < 2) {
     if ((res = mp_grow(a, 2)) != MP_OKAY) {
        return res;
     }
  }

  /* zero the int */
  mp_zero (a);

  /* read the bytes in */
  while (c-- > 0) {
    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
      return res;
    }

#ifndef MP_8BIT
      a->dp[0] |= *b++;
      a->used += 1;
#else
      a->dp[0] = (*b & MP_MASK);
      a->dp[1] |= ((*b++ >> 7U) & 1);
      a->used += 2;
#endif
  }
  mp_clamp (a);
  return MP_OKAY;
}
#endif

/* End: bn_mp_read_unsigned_bin.c */

/* Start: bn_mp_reduce.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reduces x mod m, assumes 0 < x < m**2, mu is 
 * precomputed via mp_reduce_setup.
 * From HAC pp.604 Algorithm 14.42
 */
int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
{
  mp_int  q;
  int     res, um = m->used;

  /* q = x */
  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
    return res;
  }

  /* q1 = x / b**(k-1)  */
  mp_rshd (&q, um - 1);         

  /* according to HAC this optimization is ok */
  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
      goto CLEANUP;
    }
  } else {
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
      goto CLEANUP;
    }
#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
      goto CLEANUP;
    }
#else 
    { 
      res = MP_VAL;
      goto CLEANUP;
    }
#endif
  }

  /* q3 = q2 / b**(k+1) */
  mp_rshd (&q, um + 1);         

  /* x = x mod b**(k+1), quick (no division) */
  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* q = q * m mod b**(k+1), quick (no division) */
  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* x = x - q */
  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* If x < 0, add b**(k+1) to it */
  if (mp_cmp_d (x, 0) == MP_LT) {
    mp_set (&q, 1);
    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
      goto CLEANUP;
    if ((res = mp_add (x, &q, x)) != MP_OKAY)
      goto CLEANUP;
  }

  /* Back off if it's too big */
  while (mp_cmp (x, m) != MP_LT) {
    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
      goto CLEANUP;
    }
  }
  
CLEANUP:
  mp_clear (&q);

  return res;
}
#endif

/* End: bn_mp_reduce.c */

/* Start: bn_mp_reduce_2k.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reduces a modulo n where n is of the form 2**p - d */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
{
   mp_int q;
   int    p, res;
   
   if ((res = mp_init(&q)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(n);    
top:
   /* q = a/2**p, a = a mod 2**p */
   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (d != 1) {
      /* q = q * d */
      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
         goto ERR;
      }
   }
   
   /* a = a + q */
   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (mp_cmp_mag(a, n) != MP_LT) {
      s_mp_sub(a, n, a);
      goto top;
   }
   
ERR:
   mp_clear(&q);
   return res;
}

#endif

/* End: bn_mp_reduce_2k.c */

/* Start: bn_mp_reduce_2k_l.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_L_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reduces a modulo n where n is of the form 2**p - d 
   This differs from reduce_2k since "d" can be larger
   than a single digit.
*/
int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
{
   mp_int q;
   int    p, res;
   
   if ((res = mp_init(&q)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(n);    
top:
   /* q = a/2**p, a = a mod 2**p */
   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   /* q = q * d */
   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
      goto ERR;
   }
   
   /* a = a + q */
   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (mp_cmp_mag(a, n) != MP_LT) {
      s_mp_sub(a, n, a);
      goto top;
   }
   
ERR:
   mp_clear(&q);
   return res;
}

#endif

/* End: bn_mp_reduce_2k_l.c */

/* Start: bn_mp_reduce_2k_setup.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines the setup value */
int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
{
   int res, p;
   mp_int tmp;
   
   if ((res = mp_init(&tmp)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(a);
   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   *d = tmp.dp[0];
   mp_clear(&tmp);
   return MP_OKAY;
}
#endif

/* End: bn_mp_reduce_2k_setup.c */

/* Start: bn_mp_reduce_2k_setup_l.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_SETUP_L_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines the setup value */
int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
{
   int    res;
   mp_int tmp;
   
   if ((res = mp_init(&tmp)) != MP_OKAY) {
      return res;
   }
   
   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
      goto ERR;
   }
   
   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
      goto ERR;
   }
   
ERR:
   mp_clear(&tmp);
   return res;
}
#endif

/* End: bn_mp_reduce_2k_setup_l.c */

/* Start: bn_mp_reduce_is_2k.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_IS_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines if mp_reduce_2k can be used */
int mp_reduce_is_2k(mp_int *a)
{
   int ix, iy, iw;
   mp_digit iz;
   
   if (a->used == 0) {
      return MP_NO;
   } else if (a->used == 1) {
      return MP_YES;
   } else if (a->used > 1) {
      iy = mp_count_bits(a);
      iz = 1;
      iw = 1;
    
      /* Test every bit from the second digit up, must be 1 */
      for (ix = DIGIT_BIT; ix < iy; ix++) {
          if ((a->dp[iw] & iz) == 0) {
             return MP_NO;
          }
          iz <<= 1;
          if (iz > (mp_digit)MP_MASK) {
             ++iw;
             iz = 1;
          }
      }
   }
   return MP_YES;
}

#endif

/* End: bn_mp_reduce_is_2k.c */

/* Start: bn_mp_reduce_is_2k_l.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_IS_2K_L_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* determines if reduce_2k_l can be used */
int mp_reduce_is_2k_l(mp_int *a)
{
   int ix, iy;
   
   if (a->used == 0) {
      return MP_NO;
   } else if (a->used == 1) {
      return MP_YES;
   } else if (a->used > 1) {
      /* if more than half of the digits are -1 we're sold */
      for (iy = ix = 0; ix < a->used; ix++) {
          if (a->dp[ix] == MP_MASK) {
              ++iy;
          }
      }
      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
      
   }
   return MP_NO;
}

#endif

/* End: bn_mp_reduce_is_2k_l.c */

/* Start: bn_mp_reduce_setup.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* pre-calculate the value required for Barrett reduction
 * For a given modulus "b" it calulates the value required in "a"
 */
int mp_reduce_setup (mp_int * a, mp_int * b)
{
  int     res;
  
  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
    return res;
  }
  return mp_div (a, b, a, NULL);
}
#endif

/* End: bn_mp_reduce_setup.c */

/* Start: bn_mp_rshd.c */
#include <tommath.h>
#ifdef BN_MP_RSHD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* shift right a certain amount of digits */
void mp_rshd (mp_int * a, int b)
{
  int     x;

  /* if b <= 0 then ignore it */
  if (b <= 0) {
    return;
  }

  /* if b > used then simply zero it and return */
  if (a->used <= b) {
    mp_zero (a);
    return;
  }

  {
    register mp_digit *bottom, *top;

    /* shift the digits down */

    /* bottom */
    bottom = a->dp;

    /* top [offset into digits] */
    top = a->dp + b;

    /* this is implemented as a sliding window where 
     * the window is b-digits long and digits from 
     * the top of the window are copied to the bottom
     *
     * e.g.

     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
                 /\                   |      ---->
                  \-------------------/      ---->
     */
    for (x = 0; x < (a->used - b); x++) {
      *bottom++ = *top++;
    }

    /* zero the top digits */
    for (; x < a->used; x++) {
      *bottom++ = 0;
    }
  }
  
  /* remove excess digits */
  a->used -= b;
}
#endif

/* End: bn_mp_rshd.c */

/* Start: bn_mp_set.c */
#include <tommath.h>
#ifdef BN_MP_SET_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* set to a digit */
void mp_set (mp_int * a, mp_digit b)
{
  mp_zero (a);
  a->dp[0] = b & MP_MASK;
  a->used  = (a->dp[0] != 0) ? 1 : 0;
}
#endif

/* End: bn_mp_set.c */

/* Start: bn_mp_set_int.c */
#include <tommath.h>
#ifdef BN_MP_SET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* set a 32-bit const */
int mp_set_int (mp_int * a, unsigned long b)
{
  int     x, res;

  mp_zero (a);
  
  /* set four bits at a time */
  for (x = 0; x < 8; x++) {
    /* shift the number up four bits */
    if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
      return res;
    }

    /* OR in the top four bits of the source */
    a->dp[0] |= (b >> 28) & 15;

    /* shift the source up to the next four bits */
    b <<= 4;

    /* ensure that digits are not clamped off */
    a->used += 1;
  }
  mp_clamp (a);
  return MP_OKAY;
}
#endif

/* End: bn_mp_set_int.c */

/* Start: bn_mp_shrink.c */
#include <tommath.h>
#ifdef BN_MP_SHRINK_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* shrink a bignum */
int mp_shrink (mp_int * a)
{
  mp_digit *tmp;
  int used = 1;
  
  if(a->used > 0)
    used = a->used;
  
  if (a->alloc != used) {
    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) {
      return MP_MEM;
    }
    a->dp    = tmp;
    a->alloc = used;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_shrink.c */

/* Start: bn_mp_signed_bin_size.c */
#include <tommath.h>
#ifdef BN_MP_SIGNED_BIN_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* get the size for an signed equivalent */
int mp_signed_bin_size (mp_int * a)
{
  return 1 + mp_unsigned_bin_size (a);
}
#endif

/* End: bn_mp_signed_bin_size.c */

/* Start: bn_mp_sqr.c */
#include <tommath.h>
#ifdef BN_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* computes b = a*a */
int
mp_sqr (mp_int * a, mp_int * b)
{
  int     res;

#ifdef BN_MP_TOOM_SQR_C
  /* use Toom-Cook? */
  if (a->used >= TOOM_SQR_CUTOFF) {
    res = mp_toom_sqr(a, b);
  /* Karatsuba? */
  } else 
#endif
#ifdef BN_MP_KARATSUBA_SQR_C
if (a->used >= KARATSUBA_SQR_CUTOFF) {
    res = mp_karatsuba_sqr (a, b);
  } else 
#endif
  {
#ifdef BN_FAST_S_MP_SQR_C
    /* can we use the fast comba multiplier? */
    if ((a->used * 2 + 1) < MP_WARRAY && 
         a->used < 
         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
      res = fast_s_mp_sqr (a, b);
    } else
#endif
#ifdef BN_S_MP_SQR_C
      res = s_mp_sqr (a, b);
#else
      res = MP_VAL;
#endif
  }
  b->sign = MP_ZPOS;
  return res;
}
#endif

/* End: bn_mp_sqr.c */

/* Start: bn_mp_sqrmod.c */
#include <tommath.h>
#ifdef BN_MP_SQRMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* c = a * a (mod b) */
int
mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, b, c);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_sqrmod.c */

/* Start: bn_mp_sqrt.c */
#include <tommath.h>

#ifdef BN_MP_SQRT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* this function is less generic than mp_n_root, simpler and faster */
int mp_sqrt(mp_int *arg, mp_int *ret) 
{
  int res;
  mp_int t1,t2;

  /* must be positive */
  if (arg->sign == MP_NEG) {
    return MP_VAL;
  }

  /* easy out */
  if (mp_iszero(arg) == MP_YES) {
    mp_zero(ret);
    return MP_OKAY;
  }

  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init(&t2)) != MP_OKAY) {
    goto E2;
  }

  /* First approx. (not very bad for large arg) */
  mp_rshd (&t1,t1.used/2);

  /* t1 > 0  */ 
  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
    goto E1;
  }
  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
    goto E1;
  }
  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
    goto E1;
  }
  /* And now t1 > sqrt(arg) */
  do { 
    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
      goto E1;
    }
    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
      goto E1;
    }
    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
      goto E1;
    }
    /* t1 >= sqrt(arg) >= t2 at this point */
  } while (mp_cmp_mag(&t1,&t2) == MP_GT);

  mp_exch(&t1,ret);

E1: mp_clear(&t2);
E2: mp_clear(&t1);
  return res;
}

#endif

/* End: bn_mp_sqrt.c */

/* Start: bn_mp_sub.c */
#include <tommath.h>
#ifdef BN_MP_SUB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* high level subtraction (handles signs) */
int
mp_sub (mp_int * a, mp_int * b, mp_int * c)
{
  int     sa, sb, res;

  sa = a->sign;
  sb = b->sign;

  if (sa != sb) {
    /* subtract a negative from a positive, OR */
    /* subtract a positive from a negative. */
    /* In either case, ADD their magnitudes, */
    /* and use the sign of the first number. */
    c->sign = sa;
    res = s_mp_add (a, b, c);
  } else {
    /* subtract a positive from a positive, OR */
    /* subtract a negative from a negative. */
    /* First, take the difference between their */
    /* magnitudes, then... */
    if (mp_cmp_mag (a, b) != MP_LT) {
      /* Copy the sign from the first */
      c->sign = sa;
      /* The first has a larger or equal magnitude */
      res = s_mp_sub (a, b, c);
    } else {
      /* The result has the *opposite* sign from */
      /* the first number. */
      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
      /* The second has a larger magnitude */
      res = s_mp_sub (b, a, c);
    }
  }
  return res;
}

#endif

/* End: bn_mp_sub.c */

/* Start: bn_mp_sub_d.c */
#include <tommath.h>
#ifdef BN_MP_SUB_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* single digit subtraction */
int
mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
{
  mp_digit *tmpa, *tmpc, mu;
  int       res, ix, oldused;

  /* grow c as required */
  if (c->alloc < a->used + 1) {
     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
        return res;
     }
  }

  /* if a is negative just do an unsigned
   * addition [with fudged signs]
   */
  if (a->sign == MP_NEG) {
     a->sign = MP_ZPOS;
     res     = mp_add_d(a, b, c);
     a->sign = c->sign = MP_NEG;

     /* clamp */
     mp_clamp(c);

     return res;
  }

  /* setup regs */
  oldused = c->used;
  tmpa    = a->dp;
  tmpc    = c->dp;

  /* if a <= b simply fix the single digit */
  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
     if (a->used == 1) {
        *tmpc++ = b - *tmpa;
     } else {
        *tmpc++ = b;
     }
     ix      = 1;

     /* negative/1digit */
     c->sign = MP_NEG;
     c->used = 1;
  } else {
     /* positive/size */
     c->sign = MP_ZPOS;
     c->used = a->used;

     /* subtract first digit */
     *tmpc    = *tmpa++ - b;
     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
     *tmpc++ &= MP_MASK;

     /* handle rest of the digits */
     for (ix = 1; ix < a->used; ix++) {
        *tmpc    = *tmpa++ - mu;
        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
        *tmpc++ &= MP_MASK;
     }
  }

  /* zero excess digits */
  while (ix++ < oldused) {
     *tmpc++ = 0;
  }
  mp_clamp(c);
  return MP_OKAY;
}

#endif

/* End: bn_mp_sub_d.c */

/* Start: bn_mp_submod.c */
#include <tommath.h>
#ifdef BN_MP_SUBMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* d = a - b (mod c) */
int
mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;


  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_submod.c */

/* Start: bn_mp_to_signed_bin.c */
#include <tommath.h>
#ifdef BN_MP_TO_SIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* store in signed [big endian] format */
int mp_to_signed_bin (mp_int * a, unsigned char *b)
{
  int     res;

  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
    return res;
  }
  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
  return MP_OKAY;
}
#endif

/* End: bn_mp_to_signed_bin.c */

/* Start: bn_mp_to_signed_bin_n.c */
#include <tommath.h>
#ifdef BN_MP_TO_SIGNED_BIN_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* store in signed [big endian] format */
int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
{
   if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
      return MP_VAL;
   }
   *outlen = mp_signed_bin_size(a);
   return mp_to_signed_bin(a, b);
}
#endif

/* End: bn_mp_to_signed_bin_n.c */

/* Start: bn_mp_to_unsigned_bin.c */
#include <tommath.h>
#ifdef BN_MP_TO_UNSIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* store in unsigned [big endian] format */
int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
{
  int     x, res;
  mp_int  t;

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  x = 0;
  while (mp_iszero (&t) == 0) {
#ifndef MP_8BIT
      b[x++] = (unsigned char) (t.dp[0] & 255);
#else
      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
#endif
    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
  }
  bn_reverse (b, x);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_to_unsigned_bin.c */

/* Start: bn_mp_to_unsigned_bin_n.c */
#include <tommath.h>
#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* store in unsigned [big endian] format */
int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
{
   if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
      return MP_VAL;
   }
   *outlen = mp_unsigned_bin_size(a);
   return mp_to_unsigned_bin(a, b);
}
#endif

/* End: bn_mp_to_unsigned_bin_n.c */

/* Start: bn_mp_toom_mul.c */
#include <tommath.h>
#ifdef BN_MP_TOOM_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* multiplication using the Toom-Cook 3-way algorithm 
 *
 * Much more complicated than Karatsuba but has a lower 
 * asymptotic running time of O(N**1.464).  This algorithm is 
 * only particularly useful on VERY large inputs 
 * (we're talking 1000s of digits here...).
*/
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
    int res, B;
        
    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
                             &a0, &a1, &a2, &b0, &b1, 
                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
       return res;
    }
    
    /* B */
    B = MIN(a->used, b->used) / 3;
    
    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);
    
    /* b = b2 * B**2 + b1 * B + b0 */
    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b1, B);
    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b2, B*2);
    
    /* w0 = a0*b0 */
    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w4 = a2 * b2 */
    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
       goto ERR;
    }
    

    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
       goto ERR;
    }
    
    /* now solve the matrix 
    
       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0
       
       using 12 subtractions, 4 shifts, 
              2 small divisions and 1 small multiplication 
     */
     
     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }
     
     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }     
     
     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
        goto ERR;
     }     
     
ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
                    &a0, &a1, &a2, &b0, &b1, 
                    &b2, &tmp1, &tmp2, NULL);
     return res;
}     
     
#endif

/* End: bn_mp_toom_mul.c */

/* Start: bn_mp_toom_sqr.c */
#include <tommath.h>
#ifdef BN_MP_TOOM_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* squaring using Toom-Cook 3-way algorithm */
int
mp_toom_sqr(mp_int *a, mp_int *b)
{
    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
    int res, B;

    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
       return res;
    }

    /* B */
    B = a->used / 3;

    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);

    /* w0 = a0*a0 */
    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
       goto ERR;
    }

    /* w4 = a2 * a2 */
    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
       goto ERR;
    }

    /* w1 = (a2 + 2(a1 + 2a0))**2 */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
       goto ERR;
    }

    /* w3 = (a0 + 2(a1 + 2a2))**2 */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
       goto ERR;
    }


    /* w2 = (a2 + a1 + a0)**2 */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
       goto ERR;
    }

    /* now solve the matrix

       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0

       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
     */

     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }

     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }

     if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
        goto ERR;
     }

ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
     return res;
}

#endif

/* End: bn_mp_toom_sqr.c */

/* Start: bn_mp_toradix.c */
#include <tommath.h>
#ifdef BN_MP_TORADIX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* stores a bignum as a ASCII string in a given radix (2..64) */
int mp_toradix (mp_int * a, char *str, int radix)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;
  char   *_s = str;

  /* check range of the radix */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* quick out if its zero */
  if (mp_iszero(a) == 1) {
     *str++ = '0';
     *str = '\0';
     return MP_OKAY;
  }

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* if it is negative output a - */
  if (t.sign == MP_NEG) {
    ++_s;
    *str++ = '-';
    t.sign = MP_ZPOS;
  }

  digs = 0;
  while (mp_iszero (&t) == 0) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    *str++ = mp_s_rmap[d];
    ++digs;
  }

  /* reverse the digits of the string.  In this case _s points
   * to the first digit [exluding the sign] of the number]
   */
  bn_reverse ((unsigned char *)_s, digs);

  /* append a NULL so the string is properly terminated */
  *str = '\0';

  mp_clear (&t);
  return MP_OKAY;
}

#endif

/* End: bn_mp_toradix.c */

/* Start: bn_mp_toradix_n.c */
#include <tommath.h>
#ifdef BN_MP_TORADIX_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* stores a bignum as a ASCII string in a given radix (2..64) 
 *
 * Stores upto maxlen-1 chars and always a NULL byte 
 */
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;
  char   *_s = str;

  /* check range of the maxlen, radix */
  if (maxlen < 2 || radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* quick out if its zero */
  if (mp_iszero(a) == MP_YES) {
     *str++ = '0';
     *str = '\0';
     return MP_OKAY;
  }

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* if it is negative output a - */
  if (t.sign == MP_NEG) {
    /* we have to reverse our digits later... but not the - sign!! */
    ++_s;

    /* store the flag and mark the number as positive */
    *str++ = '-';
    t.sign = MP_ZPOS;
 
    /* subtract a char */
    --maxlen;
  }

  digs = 0;
  while (mp_iszero (&t) == 0) {
    if (--maxlen < 1) {
       /* no more room */
       break;
    }
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    *str++ = mp_s_rmap[d];
    ++digs;
  }

  /* reverse the digits of the string.  In this case _s points
   * to the first digit [exluding the sign] of the number
   */
  bn_reverse ((unsigned char *)_s, digs);

  /* append a NULL so the string is properly terminated */
  *str = '\0';

  mp_clear (&t);
  return MP_OKAY;
}

#endif

/* End: bn_mp_toradix_n.c */

/* Start: bn_mp_unsigned_bin_size.c */
#include <tommath.h>
#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* get the size for an unsigned equivalent */
int mp_unsigned_bin_size (mp_int * a)
{
  int     size = mp_count_bits (a);
  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
}
#endif

/* End: bn_mp_unsigned_bin_size.c */

/* Start: bn_mp_xor.c */
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* XOR two ints together */
int
mp_xor (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {
     t.dp[ix] ^= x->dp[ix];
  }
  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_xor.c */

/* Start: bn_mp_zero.c */
#include <tommath.h>
#ifdef BN_MP_ZERO_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* set to zero */
void mp_zero (mp_int * a)
{
  int       n;
  mp_digit *tmp;

  a->sign = MP_ZPOS;
  a->used = 0;

  tmp = a->dp;
  for (n = 0; n < a->alloc; n++) {
     *tmp++ = 0;
  }
}
#endif

/* End: bn_mp_zero.c */

/* Start: bn_prime_tab.c */
#include <tommath.h>
#ifdef BN_PRIME_TAB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
const mp_digit ltm_prime_tab[] = {
  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
#ifndef MP_8BIT
  0x0083,
  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,

  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,

  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,

  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
#endif
};
#endif

/* End: bn_prime_tab.c */

/* Start: bn_reverse.c */
#include <tommath.h>
#ifdef BN_REVERSE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* reverse an array, used for radix code */
void
bn_reverse (unsigned char *s, int len)
{
  int     ix, iy;
  unsigned char t;

  ix = 0;
  iy = len - 1;
  while (ix < iy) {
    t     = s[ix];
    s[ix] = s[iy];
    s[iy] = t;
    ++ix;
    --iy;
  }
}
#endif

/* End: bn_reverse.c */

/* Start: bn_s_mp_add.c */
#include <tommath.h>
#ifdef BN_S_MP_ADD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* low level addition, based on HAC pp.594, Algorithm 14.7 */
int
s_mp_add (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int *x;
  int     olduse, res, min, max;

  /* find sizes, we let |a| <= |b| which means we have to sort
   * them.  "x" will point to the input with the most digits
   */
  if (a->used > b->used) {
    min = b->used;
    max = a->used;
    x = a;
  } else {
    min = a->used;
    max = b->used;
    x = b;
  }

  /* init result */
  if (c->alloc < max + 1) {
    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* get old used digit count and set new one */
  olduse = c->used;
  c->used = max + 1;

  {
    register mp_digit u, *tmpa, *tmpb, *tmpc;
    register int i;

    /* alias for digit pointers */

    /* first input */
    tmpa = a->dp;

    /* second input */
    tmpb = b->dp;

    /* destination */
    tmpc = c->dp;

    /* zero the carry */
    u = 0;
    for (i = 0; i < min; i++) {
      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
      *tmpc = *tmpa++ + *tmpb++ + u;

      /* U = carry bit of T[i] */
      u = *tmpc >> ((mp_digit)DIGIT_BIT);

      /* take away carry bit from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* now copy higher words if any, that is in A+B 
     * if A or B has more digits add those in 
     */
    if (min != max) {
      for (; i < max; i++) {
        /* T[i] = X[i] + U */
        *tmpc = x->dp[i] + u;

        /* U = carry bit of T[i] */
        u = *tmpc >> ((mp_digit)DIGIT_BIT);

        /* take away carry bit from T[i] */
        *tmpc++ &= MP_MASK;
      }
    }

    /* add carry */
    *tmpc++ = u;

    /* clear digits above oldused */
    for (i = c->used; i < olduse; i++) {
      *tmpc++ = 0;
    }
  }

  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_add.c */

/* Start: bn_s_mp_exptmod.c */
#include <tommath.h>
#ifdef BN_S_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
{
  mp_int  M[TAB_SIZE], res, mu;
  mp_digit buf;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
  int (*redux)(mp_int*,mp_int*,mp_int*);

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
    if (winsize > 5) {
       winsize = 5;
    }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err; 
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* create mu, used for Barrett reduction */
  if ((err = mp_init (&mu)) != MP_OKAY) {
    goto LBL_M;
  }
  
  if (redmode == 0) {
     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
        goto LBL_MU;
     }
     redux = mp_reduce;
  } else {
     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
        goto LBL_MU;
     }
     redux = mp_reduce_2k_l;
  }    

  /* create M table
   *
   * The M table contains powers of the base, 
   * e.g. M[x] = G**x mod P
   *
   * The first half of the table is not 
   * computed though accept for M[0] and M[1]
   */
  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
    goto LBL_MU;
  }

  /* compute the value at M[1<<(winsize-1)] by squaring 
   * M[1] (winsize-1) times 
   */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_MU;
  }

  for (x = 0; x < (winsize - 1); x++) {
    /* square it */
    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
                       &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_MU;
    }

    /* reduce modulo P */
    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
   */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_MU;
  }
  mp_set (&res, 1);

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset the bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int) DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_MU:mp_clear (&mu);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif

/* End: bn_s_mp_exptmod.c */

/* Start: bn_s_mp_mul_digs.c */
#include <tommath.h>
#ifdef BN_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* multiplies |a| * |b| and only computes upto digs digits of result
 * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
 * many digits of output are created.
 */
int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  mp_int  t;
  int     res, pa, pb, ix, iy;
  mp_digit u;
  mp_word r;
  mp_digit tmpx, *tmpt, *tmpy;

  /* can we use the fast multiplier? */
  if (((digs) < MP_WARRAY) &&
      MIN (a->used, b->used) < 
          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_s_mp_mul_digs (a, b, c, digs);
  }

  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
    return res;
  }
  t.used = digs;

  /* compute the digits of the product directly */
  pa = a->used;
  for (ix = 0; ix < pa; ix++) {
    /* set the carry to zero */
    u = 0;

    /* limit ourselves to making digs digits of output */
    pb = MIN (b->used, digs - ix);

    /* setup some aliases */
    /* copy of the digit from a used within the nested loop */
    tmpx = a->dp[ix];
    
    /* an alias for the destination shifted ix places */
    tmpt = t.dp + ix;
    
    /* an alias for the digits of b */
    tmpy = b->dp;

    /* compute the columns of the output and propagate the carry */
    for (iy = 0; iy < pb; iy++) {
      /* compute the column as a mp_word */
      r       = ((mp_word)*tmpt) +
                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
                ((mp_word) u);

      /* the new column is the lower part of the result */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get the carry word from the result */
      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
    }
    /* set carry if it is placed below digs */
    if (ix + iy < digs) {
      *tmpt = u;
    }
  }

  mp_clamp (&t);
  mp_exch (&t, c);

  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_mul_digs.c */

/* Start: bn_s_mp_mul_high_digs.c */
#include <tommath.h>
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* multiplies |a| * |b| and does not compute the lower digs digits
 * [meant to get the higher part of the product]
 */
int
s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  mp_int  t;
  int     res, pa, pb, ix, iy;
  mp_digit u;
  mp_word r;
  mp_digit tmpx, *tmpt, *tmpy;

  /* can we use the fast multiplier? */
#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
  if (((a->used + b->used + 1) < MP_WARRAY)
      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_s_mp_mul_high_digs (a, b, c, digs);
  }
#endif

  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
    return res;
  }
  t.used = a->used + b->used + 1;

  pa = a->used;
  pb = b->used;
  for (ix = 0; ix < pa; ix++) {
    /* clear the carry */
    u = 0;

    /* left hand side of A[ix] * B[iy] */
    tmpx = a->dp[ix];

    /* alias to the address of where the digits will be stored */
    tmpt = &(t.dp[digs]);

    /* alias for where to read the right hand side from */
    tmpy = b->dp + (digs - ix);

    for (iy = digs - ix; iy < pb; iy++) {
      /* calculate the double precision result */
      r       = ((mp_word)*tmpt) +
                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
                ((mp_word) u);

      /* get the lower part */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* carry the carry */
      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
    }
    *tmpt = u;
  }
  mp_clamp (&t);
  mp_exch (&t, c);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_mul_high_digs.c */

/* Start: bn_s_mp_sqr.c */
#include <tommath.h>
#ifdef BN_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
int s_mp_sqr (mp_int * a, mp_int * b)
{
  mp_int  t;
  int     res, ix, iy, pa;
  mp_word r;
  mp_digit u, tmpx, *tmpt;

  pa = a->used;
  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
    return res;
  }

  /* default used is maximum possible size */
  t.used = 2*pa + 1;

  for (ix = 0; ix < pa; ix++) {
    /* first calculate the digit at 2*ix */
    /* calculate double precision result */
    r = ((mp_word) t.dp[2*ix]) +
        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);

    /* store lower part in result */
    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));

    /* get the carry */
    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));

    /* left hand side of A[ix] * A[iy] */
    tmpx        = a->dp[ix];

    /* alias for where to store the results */
    tmpt        = t.dp + (2*ix + 1);
    
    for (iy = ix + 1; iy < pa; iy++) {
      /* first calculate the product */
      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);

      /* now calculate the double precision result, note we use
       * addition instead of *2 since it's easier to optimize
       */
      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);

      /* store lower part */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get carry */
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
    /* propagate upwards */
    while (u != ((mp_digit) 0)) {
      r       = ((mp_word) *tmpt) + ((mp_word) u);
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
  }

  mp_clamp (&t);
  mp_exch (&t, b);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_sqr.c */

/* Start: bn_s_mp_sub.c */
#include <tommath.h>
#ifdef BN_S_MP_SUB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
int
s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
{
  int     olduse, res, min, max;

  /* find sizes */
  min = b->used;
  max = a->used;

  /* init result */
  if (c->alloc < max) {
    if ((res = mp_grow (c, max)) != MP_OKAY) {
      return res;
    }
  }
  olduse = c->used;
  c->used = max;

  {
    register mp_digit u, *tmpa, *tmpb, *tmpc;
    register int i;

    /* alias for digit pointers */
    tmpa = a->dp;
    tmpb = b->dp;
    tmpc = c->dp;

    /* set carry to zero */
    u = 0;
    for (i = 0; i < min; i++) {
      /* T[i] = A[i] - B[i] - U */
      *tmpc = *tmpa++ - *tmpb++ - u;

      /* U = carry bit of T[i]
       * Note this saves performing an AND operation since
       * if a carry does occur it will propagate all the way to the
       * MSB.  As a result a single shift is enough to get the carry
       */
      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));

      /* Clear carry from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* now copy higher words if any, e.g. if A has more digits than B  */
    for (; i < max; i++) {
      /* T[i] = A[i] - U */
      *tmpc = *tmpa++ - u;

      /* U = carry bit of T[i] */
      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));

      /* Clear carry from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* clear digits above used (since we may not have grown result above) */
    for (i = c->used; i < olduse; i++) {
      *tmpc++ = 0;
    }
  }

  mp_clamp (c);
  return MP_OKAY;
}

#endif

/* End: bn_s_mp_sub.c */

/* Start: bncore.c */
#include <tommath.h>
#ifdef BNCORE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */

/* Known optimal configurations

 CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
-------------------------------------------------------------
 Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
 AMD Athlon64           /GCC v3.4.4   /        80/       120/LTM 0.35
 
*/

int     KARATSUBA_MUL_CUTOFF = 80,      /* Min. number of digits before Karatsuba multiplication is used. */
        KARATSUBA_SQR_CUTOFF = 120,     /* Min. number of digits before Karatsuba squaring is used. */
        
        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
        TOOM_SQR_CUTOFF      = 400; 
#endif

/* End: bncore.c */


/* EOF */

Added libtommath/pretty.build.





































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#!/bin/perl -w
#
# Cute little builder for perl 
# Total waste of development time...
#
# This will build all the object files and then the archive .a file
# requires GCC, GNU make and a sense of humour.
#
# Tom St Denis
use strict;

my $count = 0;
my $starttime = time;
my $rate  = 0;
print "Scanning for source files...\n";
foreach my $filename (glob "*.c") {
       ++$count;
}
print "Source files to build: $count\nBuilding...\n";
my $i = 0;
my $lines = 0;
my $filesbuilt = 0;
foreach my $filename (glob "*.c") {
       printf("Building %3.2f%%, ", (++$i/$count)*100.0);
       if ($i % 4 == 0) { print "/, "; }
       if ($i % 4 == 1) { print "-, "; }
       if ($i % 4 == 2) { print "\\, "; }
       if ($i % 4 == 3) { print "|, "; }
       if ($rate > 0) {
           my $tleft = ($count - $i) / $rate;
           my $tsec  = $tleft%60;
           my $tmin  = ($tleft/60)%60;
           my $thour = ($tleft/3600)%60;
           printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec);
       }
       my $cnt = ($i/$count)*30.0;
       my $x   = 0;
       print "[";
       for (; $x < $cnt; $x++) { print "#"; }
       for (; $x < 30; $x++)   { print " "; }
       print "]\r";
       my $tmp = $filename;
       $tmp =~ s/\.c/".o"/ge;
       if (open(SRC, "<$tmp")) {
          close SRC;
       } else {
          !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n";
          open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
          ++$lines while (<SRC>);
          close SRC or die "Error closing $filename after reading: $!";
          ++$filesbuilt;
       }      

       # update timer 
       if (time != $starttime) {
          my $delay = time - $starttime;
          $rate = $i/$delay;
       }
}

# finish building the library 
printf("\nFinished building source (%d seconds, %3.2f files per second).\n", time - $starttime, $rate);
print "Compiled approximately $filesbuilt files and $lines lines of code.\n";
print "Doing final make (building archive...)\n";
!system("make > /dev/null 2>/dev/null") or die "\nERROR: Failed to perform last make command!!!\n";
print "done.\n";

Added libtommath/tombc/grammar.txt.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
program       := program statement | statement | empty
statement     := { statement }                                                                              | 
                 identifier = numexpression;                                                                | 
                 identifier[numexpression] = numexpression;                                                 |
                 function(expressionlist);                                                                  | 
                 for (identifer = numexpression; numexpression; identifier = numexpression) { statement }   |
                 while (numexpression) { statement }                                                        | 
                 if (numexpresion) { statement } elif                                                       | 
                 break;                                                                                     | 
                 continue;                                                                                  
                 
elif          := else statement | empty
function      := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit
expressionlist := expressionlist, expression | expression

// LR(1) !!!?
expression    := string | numexpression
numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr
cmpexpr       := boolexpr  < boolexpr | boolexpr  > boolexpr | boolexpr == boolexpr | 
                 boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr
boolexpr      := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr
shiftexpr     := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr
addsubexpr    := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr
mulexpr       := expr * expr       | expr / expr | expr % expr | expr
expr          := -nexpr | nexpr 
nexpr         := integer | identifier | ( numexpression ) | identifier[numexpression] 

identifier    := identifer digits | identifier alpha | alpha
alpha         := a ... z | A ... Z
integer       := hexnumber | digits 
hexnumber     := 0xhexdigits
hexdigits     := hexdigits hexdigit | hexdigit
hexdigit      := 0 ... 9 | a ... f | A ... F
digits        := digits digit | digit 
digit         := 0 ... 9

Changes to libtommath/tommath.h.

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
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */













#ifndef BN_H_
#define BN_H_


#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>



#ifndef MIN
   #define MIN(x,y) ((x)<(y)?(x):(y))
#endif

#ifndef MAX
   #define MAX(x,y) ((x)>(y)?(x):(y))
#endif

#ifndef MP_NO_FILE
#  include <stdio.h>
#endif

#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

#else

/* C on the other hand doesn't care */
#define  OPT_CAST(x)

#endif


/* detect 64-bit mode if possible */
#if defined(__x86_64__)
   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
      #define MP_64BIT
   #endif
#endif

/* some default configurations.
 *
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>



>




>
>









<
<
<
<















|







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
/* LibTomMath, multiple-precision integer library -- Tom St Denis

 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, [email protected], http://math.libtomcrypt.com
 */
#ifndef BN_H_
#define BN_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

#include <tommath_class.h>

#ifndef MIN
   #define MIN(x,y) ((x)<(y)?(x):(y))
#endif

#ifndef MAX
   #define MAX(x,y) ((x)>(y)?(x):(y))
#endif





#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

#else

/* C on the other hand doesn't care */
#define  OPT_CAST(x)

#endif


/* detect 64-bit mode if possible */
#if defined(__x86_64__) 
   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
      #define MP_64BIT
   #endif
#endif

/* some default configurations.
 *
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

   typedef unsigned long      mp_digit;
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */

   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__)
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

   typedef unsigned long      mp_digit;
   typedef ulong64            mp_word;

#ifdef MP_31BIT
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif
#endif

/* define heap macros */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);







|


|











|






|





|







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

   typedef unsigned long      mp_digit;
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */
   
   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__) 
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

   typedef unsigned long      mp_digit;
   typedef ulong64            mp_word;

#ifdef MP_31BIT   
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif   
#endif

/* define heap macros */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC 
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);
117
118
119
120
121
122
123
















124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

















/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

#ifdef MP_USE_ENUMS
typedef enum {
   MP_ZPOS = 0,
   MP_NEG = 1
} mp_sign;
typedef enum {
   MP_LT = -1,
   MP_EQ = 0,
   MP_GT = 1
} mp_ord;
typedef enum {
   MP_NO = 0,
   MP_YES = 1
} mp_bool;
typedef enum {
   MP_OKAY  = 0,
   MP_ERR   = -1,
   MP_MEM   = -2,
   MP_VAL   = -3,
   MP_ITER  = -4
} mp_err;
#else
typedef int mp_sign;
#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */
typedef int mp_ord;
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */
typedef int mp_bool;
#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */
typedef int mp_err;
#define MP_OKAY       0   /* ok result */
#define MP_ERR        -1  /* unknown error */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL
#define MP_ITER       -4  /* Max. iterations reached */
#endif

/* tunable cutoffs */

#ifndef MP_FIXED_CUTOFFS
extern int
KARATSUBA_MUL_CUTOFF,
KARATSUBA_SQR_CUTOFF,
TOOM_MUL_CUTOFF,
TOOM_SQR_CUTOFF;
#endif

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
#   ifndef MP_LOW_MEM
#      define MP_PREC 32        /* default digits of precision */
#   elif defined(MP_8BIT)
#      define MP_PREC 16        /* default digits of precision */
#   else
#      define MP_PREC 8         /* default digits of precision */
#   endif
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
typedef struct  {
   int used, alloc;
   mp_sign sign;
   mp_digit *dp;
} mp_int;

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
const char *mp_error_to_string(mp_err code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
mp_err mp_init(mp_int *a);

/* free a bignum */
void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
mp_err mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
mp_err mp_shrink(mp_int *a);

/* grow an int to a given size */
mp_err mp_grow(mp_int *a, int size);

/* init to a given number of digits */
mp_err mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)

/* set to zero */
void mp_zero(mp_int *a);

/* set to a digit */
void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
mp_err mp_copy(const mp_int *a, mp_int *b);

/* inits and copies, a = b */
mp_err mp_init_copy(mp_int *a, const mp_int *b);

/* trim unused digits */
void mp_clamp(mp_int *a);

/* import binary data */
mp_err mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, const void *op);

/* export binary data */
mp_err mp_export(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, const mp_int *op);

/* ---> digit manipulation <--- */

/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
mp_err mp_lshd(mp_int *a, int b);

/* c = a / 2**b, implemented as c = a >> b */
mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
mp_err mp_div_2(const mp_int *a, mp_int *b);

/* c = a * 2**b, implemented as c = a << b */
mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c);

/* b = a*2 */
mp_err mp_mul_2(const mp_int *a, mp_int *b);

/* c = a mod 2**b */
mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
mp_err mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(const mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
mp_err mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b (two complement) */
mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a OR b (two complement) */
mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a AND b (two complement) */
mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
mp_err mp_neg(const mp_int *a, mp_int *b);

/* b = |a| */
mp_err mp_abs(const mp_int *a, mp_int *b);

/* compare a to b */
mp_ord mp_cmp(const mp_int *a, const mp_int *b);

/* compare |a| to |b| */
mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b);

/* c = a + b */
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a - b */
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);

/* c = a * b */
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);

/* b = a*a  */
mp_err mp_sqr(const mp_int *a, mp_int *b);

/* a/b => cb + d == a */
mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
mp_ord mp_cmp_d(const mp_int *a, mp_digit b);

/* c = a + b */
mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c);

/* Increment "a" by one like "a++". Changes input! */
mp_err mp_incr(mp_int *a);

/* c = a - b */
mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c);

/* Decrement "a" by one like "a--". Changes input! */
mp_err mp_decr(mp_int *a);

/* c = a * b */
mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* d = a - b (mod c) */
mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* d = a * b (mod c) */
mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d);

/* c = a * a (mod b) */
mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c);

/* c = (a, b) */
mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
mp_err mp_sqrt(const mp_int *arg, mp_int *ret);

/* is number a square? */
mp_err mp_is_square(const mp_int *arg, mp_bool *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
mp_err mp_reduce_setup(mp_int *a, const mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code].
 */
mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);

/* setups the montgomery reduction */
mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho);

/* returns 1 if a is a valid DR modulus */
mp_bool mp_dr_is_modulus(const mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(const mp_int *a, mp_digit *d);

/* reduces a modulo n using the Diminished Radix method */
mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k);

/* returns true if a can be reduced with mp_reduce_2k */
mp_bool mp_reduce_is_2k(const mp_int *a);

/* determines k value for 2k reduction */
mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d);

/* returns true if a can be reduced with mp_reduce_2k_l */
mp_bool mp_reduce_is_2k_l(const mp_int *a);

/* determines k value for 2k reduction */
mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d);

/* Y = G**X (mod P) */
mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
mp_err mp_prime_is_divisible(mp_int *a, mp_bool *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96
 */
int mp_prime_rabin_miller_trials(int size);

/* performs one strong Lucas-Selfridge test of "a".
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result);

/* performs one Frobenius test of "a" as described by Paul Underwood.
 * Sets result to 0 if composite or 1 if probable prime
 */
mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result);

/* performs t random rounds of Miller-Rabin on "a" additional to
 * bases 2 and 3.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 * Both a strong Lucas-Selfridge to complete the BPSW test
 * and a separate Frobenius test are available at compile time.
 * With t<0 a deterministic test is run for primes up to
 * 318665857834031151167461. With t<13 (abs(t)-13) additional
 * tests with sequential small primes are run starting at 43.
 * Is Fips 186.4 compliant if called with t as computed by
 * mp_prime_rabin_miller_trials();
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 *
 *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
 *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)

 *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);

/* Integer logarithm to integer base */
mp_err mp_ilogb(const mp_int *a, mp_digit base, mp_int *c);

/* ---> radix conversion <--- */
int mp_count_bits(const mp_int *a);

int mp_unsigned_bin_size(const mp_int *a);
mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b);
mp_err mp_to_unsigned_bin_n(const mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_signed_bin_size(const mp_int *a);
mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
mp_err mp_to_signed_bin(const mp_int *a,  unsigned char *b);
mp_err mp_to_signed_bin_n(const mp_int * a, unsigned char *b, unsigned long *outlen);

mp_err mp_read_radix(mp_int *a, const char *str, int radix);
mp_err mp_toradix(const mp_int *a, char *str, int radix);
mp_err mp_toradix_n(const mp_int * a, char *str, int radix, int maxlen);
mp_err mp_radix_size(const mp_int *a, int radix, int *size);

#ifndef MP_NO_FILE
mp_err mp_fread(mp_int *a, int radix, FILE *stream);
mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream);
#endif

#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
<
<
|
|
|
|
<






|
|
<
<
|
|
|







|
<
|











|



|





|








|


|


|





<




















|


|




<
<
<
<
<
<






|

|
|


|

|
|


|

|
|


|


|




|


|
|

|
|

|
|




|


|


|


|


|


|


|


|


|


|




|


|

<
<
<

|

<
<
<

|


|


|


|


|




|


|


|


|


|


|


|


|








|


|





|



|
|

|


|




|


|


|


|

|
|


|


|


|


|


|


|

|
|














|




|




|


|



<
<
<
<
<
<
<
<
<
<
|
|


<
<
<
<
<
<
<



|






|


|












|
|
|
>
|






|

<
<
<

|

|
|
|
|

|
|
|
|

|
|
|
|

<
|
|
<







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154






















155

















156

157


158
159
160
161

162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251






252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335



336
337
338



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475










476
477
478
479







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518



519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538

539
540
541
542
543
544
545
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

/* equalities */
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */

#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */

#define MP_OKAY       0   /* ok result */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL

#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */























typedef int           mp_err;



















/* you'll have to tune these... */


extern int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;


/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
   #ifndef MP_LOW_MEM
      #define MP_PREC                 32     /* default digits of precision */


   #else
      #define MP_PREC                 8      /* default digits of precision */
   #endif   
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
typedef struct  {
    int used, alloc, sign;

    mp_digit *dp;
} mp_int;

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
char *mp_error_to_string(int code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
int mp_init(mp_int *a);

/* free a bignum */
void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
int mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
int mp_shrink(mp_int *a);

/* grow an int to a given size */
int mp_grow(mp_int *a, int size);

/* init to a given number of digits */
int mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)


/* set to zero */
void mp_zero(mp_int *a);

/* set to a digit */
void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);

/* inits and copies, a = b */
int mp_init_copy(mp_int *a, mp_int *b);

/* trim unused digits */
void mp_clamp(mp_int *a);







/* ---> digit manipulation <--- */

/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
int mp_lshd(mp_int *a, int b);

/* c = a / 2**b */
int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
int mp_div_2(mp_int *a, mp_int *b);

/* c = a * 2**b */
int mp_mul_2d(mp_int *a, int b, mp_int *c);

/* b = a*2 */
int mp_mul_2(mp_int *a, mp_int *b);

/* c = a mod 2**d */
int mp_mod_2d(mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
int mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b  */
int mp_xor(mp_int *a, mp_int *b, mp_int *c);

/* c = a OR b */
int mp_or(mp_int *a, mp_int *b, mp_int *c);

/* c = a AND b */
int mp_and(mp_int *a, mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
int mp_neg(mp_int *a, mp_int *b);

/* b = |a| */
int mp_abs(mp_int *a, mp_int *b);

/* compare a to b */
int mp_cmp(mp_int *a, mp_int *b);

/* compare |a| to |b| */
int mp_cmp_mag(mp_int *a, mp_int *b);

/* c = a + b */
int mp_add(mp_int *a, mp_int *b, mp_int *c);

/* c = a - b */
int mp_sub(mp_int *a, mp_int *b, mp_int *c);

/* c = a * b */
int mp_mul(mp_int *a, mp_int *b, mp_int *c);

/* b = a*a  */
int mp_sqr(mp_int *a, mp_int *b);

/* a/b => cb + d == a */
int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
int mp_mod(mp_int *a, mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
int mp_cmp_d(mp_int *a, mp_digit b);

/* c = a + b */
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);




/* c = a - b */
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);




/* c = a * b */
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a - b (mod c) */
int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a * b (mod c) */
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a * a (mod b) */
int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
int mp_invmod(mp_int *a, mp_int *b, mp_int *c);

/* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
int mp_sqrt(mp_int *arg, mp_int *ret);

/* is number a square? */
int mp_is_square(mp_int *arg, int *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
int mp_reduce_setup(mp_int *a, mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
 */
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);

/* setups the montgomery reduction */
int mp_montgomery_setup(mp_int *a, mp_digit *mp);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);

/* returns 1 if a is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b using the Diminished Radix method */
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);

/* returns true if a can be reduced with mp_reduce_2k */
int mp_reduce_is_2k(mp_int *a);

/* determines k value for 2k reduction */
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);

/* returns true if a can be reduced with mp_reduce_2k_l */
int mp_reduce_is_2k_l(mp_int *a);

/* determines k value for 2k reduction */
int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);

/* d = a**b (mod c) */
int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
int mp_prime_is_divisible(mp_int *a, int *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96 
 */
int mp_prime_rabin_miller_trials(int size);











/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.







 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
int mp_prime_is_prime(mp_int *a, int t, int *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4 
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);




/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);

int mp_unsigned_bin_size(mp_int *a);
int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a,  unsigned char *b);
int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);

int mp_read_radix(mp_int *a, const char *str, int radix);
int mp_toradix(mp_int *a, char *str, int radix);
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
int mp_radix_size(mp_int *a, int radix, int *size);


int mp_fread(mp_int *a, int radix, FILE *stream);
int mp_fwrite(mp_int *a, int radix, FILE *stream);


#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))

Added libtommath/tommath.out.























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
\BOOKMARK [0][-]{chapter.1}{Introduction}{}
\BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1}
\BOOKMARK [2][-]{subsection.1.1.1}{What is Multiple Precision Arithmetic?}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.2}{The Need for Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1}
\BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1}
\BOOKMARK [2][-]{subsection.1.3.1}{Notation}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.2}{Precision Notation}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.3}{Algorithm Inputs and Outputs}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3}
\BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1}
\BOOKMARK [1][-]{section.1.5}{Introduction to LibTomMath}{chapter.1}
\BOOKMARK [2][-]{subsection.1.5.1}{What is LibTomMath?}{section.1.5}
\BOOKMARK [2][-]{subsection.1.5.2}{Goals of LibTomMath}{section.1.5}
\BOOKMARK [1][-]{section.1.6}{Choice of LibTomMath}{chapter.1}
\BOOKMARK [2][-]{subsection.1.6.1}{Code Base}{section.1.6}
\BOOKMARK [2][-]{subsection.1.6.2}{API Simplicity}{section.1.6}
\BOOKMARK [2][-]{subsection.1.6.3}{Optimizations}{section.1.6}
\BOOKMARK [2][-]{subsection.1.6.4}{Portability and Stability}{section.1.6}
\BOOKMARK [2][-]{subsection.1.6.5}{Choice}{section.1.6}
\BOOKMARK [0][-]{chapter.2}{Getting Started}{}
\BOOKMARK [1][-]{section.2.1}{Library Basics}{chapter.2}
\BOOKMARK [1][-]{section.2.2}{What is a Multiple Precision Integer?}{chapter.2}
\BOOKMARK [2][-]{subsection.2.2.1}{The mp\137int Structure}{section.2.2}
\BOOKMARK [1][-]{section.2.3}{Argument Passing}{chapter.2}
\BOOKMARK [1][-]{section.2.4}{Return Values}{chapter.2}
\BOOKMARK [1][-]{section.2.5}{Initialization and Clearing}{chapter.2}
\BOOKMARK [2][-]{subsection.2.5.1}{Initializing an mp\137int}{section.2.5}
\BOOKMARK [2][-]{subsection.2.5.2}{Clearing an mp\137int}{section.2.5}
\BOOKMARK [1][-]{section.2.6}{Maintenance Algorithms}{chapter.2}
\BOOKMARK [2][-]{subsection.2.6.1}{Augmenting an mp\137int's Precision}{section.2.6}
\BOOKMARK [2][-]{subsection.2.6.2}{Initializing Variable Precision mp\137ints}{section.2.6}
\BOOKMARK [2][-]{subsection.2.6.3}{Multiple Integer Initializations and Clearings}{section.2.6}
\BOOKMARK [2][-]{subsection.2.6.4}{Clamping Excess Digits}{section.2.6}
\BOOKMARK [0][-]{chapter.3}{Basic Operations}{}
\BOOKMARK [1][-]{section.3.1}{Introduction}{chapter.3}
\BOOKMARK [1][-]{section.3.2}{Assigning Values to mp\137int Structures}{chapter.3}
\BOOKMARK [2][-]{subsection.3.2.1}{Copying an mp\137int}{section.3.2}
\BOOKMARK [2][-]{subsection.3.2.2}{Creating a Clone}{section.3.2}
\BOOKMARK [1][-]{section.3.3}{Zeroing an Integer}{chapter.3}
\BOOKMARK [1][-]{section.3.4}{Sign Manipulation}{chapter.3}
\BOOKMARK [2][-]{subsection.3.4.1}{Absolute Value}{section.3.4}
\BOOKMARK [2][-]{subsection.3.4.2}{Integer Negation}{section.3.4}
\BOOKMARK [1][-]{section.3.5}{Small Constants}{chapter.3}
\BOOKMARK [2][-]{subsection.3.5.1}{Setting Small Constants}{section.3.5}
\BOOKMARK [2][-]{subsection.3.5.2}{Setting Large Constants}{section.3.5}
\BOOKMARK [1][-]{section.3.6}{Comparisons}{chapter.3}
\BOOKMARK [2][-]{subsection.3.6.1}{Unsigned Comparisions}{section.3.6}
\BOOKMARK [2][-]{subsection.3.6.2}{Signed Comparisons}{section.3.6}
\BOOKMARK [0][-]{chapter.4}{Basic Arithmetic}{}
\BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4}
\BOOKMARK [1][-]{section.4.2}{Addition and Subtraction}{chapter.4}
\BOOKMARK [2][-]{subsection.4.2.1}{Low Level Addition}{section.4.2}
\BOOKMARK [2][-]{subsection.4.2.2}{Low Level Subtraction}{section.4.2}
\BOOKMARK [2][-]{subsection.4.2.3}{High Level Addition}{section.4.2}
\BOOKMARK [2][-]{subsection.4.2.4}{High Level Subtraction}{section.4.2}
\BOOKMARK [1][-]{section.4.3}{Bit and Digit Shifting}{chapter.4}
\BOOKMARK [2][-]{subsection.4.3.1}{Multiplication by Two}{section.4.3}
\BOOKMARK [2][-]{subsection.4.3.2}{Division by Two}{section.4.3}
\BOOKMARK [1][-]{section.4.4}{Polynomial Basis Operations}{chapter.4}
\BOOKMARK [2][-]{subsection.4.4.1}{Multiplication by x}{section.4.4}
\BOOKMARK [2][-]{subsection.4.4.2}{Division by x}{section.4.4}
\BOOKMARK [1][-]{section.4.5}{Powers of Two}{chapter.4}
\BOOKMARK [2][-]{subsection.4.5.1}{Multiplication by Power of Two}{section.4.5}
\BOOKMARK [2][-]{subsection.4.5.2}{Division by Power of Two}{section.4.5}
\BOOKMARK [2][-]{subsection.4.5.3}{Remainder of Division by Power of Two}{section.4.5}
\BOOKMARK [0][-]{chapter.5}{Multiplication and Squaring}{}
\BOOKMARK [1][-]{section.5.1}{The Multipliers}{chapter.5}
\BOOKMARK [1][-]{section.5.2}{Multiplication}{chapter.5}
\BOOKMARK [2][-]{subsection.5.2.1}{The Baseline Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.2}{Faster Multiplication by the ``Comba'' Method}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.3}{Polynomial Basis Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.4}{Karatsuba Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.5}{Toom-Cook 3-Way Multiplication}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.6}{Signed Multiplication}{section.5.2}
\BOOKMARK [1][-]{section.5.3}{Squaring}{chapter.5}
\BOOKMARK [2][-]{subsection.5.3.1}{The Baseline Squaring Algorithm}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.2}{Faster Squaring by the ``Comba'' Method}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.3}{Polynomial Basis Squaring}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.4}{Karatsuba Squaring}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.5}{Toom-Cook Squaring}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.6}{High Level Squaring}{section.5.3}
\BOOKMARK [0][-]{chapter.6}{Modular Reduction}{}
\BOOKMARK [1][-]{section.6.1}{Basics of Modular Reduction}{chapter.6}
\BOOKMARK [1][-]{section.6.2}{The Barrett Reduction}{chapter.6}
\BOOKMARK [2][-]{subsection.6.2.1}{Fixed Point Arithmetic}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.2}{Choosing a Radix Point}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.3}{Trimming the Quotient}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.4}{Trimming the Residue}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.5}{The Barrett Algorithm}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.6}{The Barrett Setup Algorithm}{section.6.2}
\BOOKMARK [1][-]{section.6.3}{The Montgomery Reduction}{chapter.6}
\BOOKMARK [2][-]{subsection.6.3.1}{Digit Based Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.2}{Baseline Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.3}{Faster ``Comba'' Montgomery Reduction}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.4}{Montgomery Setup}{section.6.3}
\BOOKMARK [1][-]{section.6.4}{The Diminished Radix Algorithm}{chapter.6}
\BOOKMARK [2][-]{subsection.6.4.1}{Choice of Moduli}{section.6.4}
\BOOKMARK [2][-]{subsection.6.4.2}{Choice of k}{section.6.4}
\BOOKMARK [2][-]{subsection.6.4.3}{Restricted Diminished Radix Reduction}{section.6.4}
\BOOKMARK [2][-]{subsection.6.4.4}{Unrestricted Diminished Radix Reduction}{section.6.4}
\BOOKMARK [1][-]{section.6.5}{Algorithm Comparison}{chapter.6}
\BOOKMARK [0][-]{chapter.7}{Exponentiation}{}
\BOOKMARK [1][-]{section.7.1}{Exponentiation Basics}{chapter.7}
\BOOKMARK [2][-]{subsection.7.1.1}{Single Digit Exponentiation}{section.7.1}
\BOOKMARK [1][-]{section.7.2}{k-ary Exponentiation}{chapter.7}
\BOOKMARK [2][-]{subsection.7.2.1}{Optimal Values of k}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.2}{Sliding-Window Exponentiation}{section.7.2}
\BOOKMARK [1][-]{section.7.3}{Modular Exponentiation}{chapter.7}
\BOOKMARK [2][-]{subsection.7.3.1}{Barrett Modular Exponentiation}{section.7.3}
\BOOKMARK [1][-]{section.7.4}{Quick Power of Two}{chapter.7}
\BOOKMARK [0][-]{chapter.8}{Higher Level Algorithms}{}
\BOOKMARK [1][-]{section.8.1}{Integer Division with Remainder}{chapter.8}
\BOOKMARK [2][-]{subsection.8.1.1}{Quotient Estimation}{section.8.1}
\BOOKMARK [2][-]{subsection.8.1.2}{Normalized Integers}{section.8.1}
\BOOKMARK [2][-]{subsection.8.1.3}{Radix- Division with Remainder}{section.8.1}
\BOOKMARK [1][-]{section.8.2}{Single Digit Helpers}{chapter.8}
\BOOKMARK [2][-]{subsection.8.2.1}{Single Digit Addition and Subtraction}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.2}{Single Digit Multiplication}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.3}{Single Digit Division}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.4}{Single Digit Root Extraction}{section.8.2}
\BOOKMARK [1][-]{section.8.3}{Random Number Generation}{chapter.8}
\BOOKMARK [1][-]{section.8.4}{Formatted Representations}{chapter.8}
\BOOKMARK [2][-]{subsection.8.4.1}{Reading Radix-n Input}{section.8.4}
\BOOKMARK [2][-]{subsection.8.4.2}{Generating Radix-n Output}{section.8.4}
\BOOKMARK [0][-]{chapter.9}{Number Theoretic Algorithms}{}
\BOOKMARK [1][-]{section.9.1}{Greatest Common Divisor}{chapter.9}
\BOOKMARK [2][-]{subsection.9.1.1}{Complete Greatest Common Divisor}{section.9.1}
\BOOKMARK [1][-]{section.9.2}{Least Common Multiple}{chapter.9}
\BOOKMARK [1][-]{section.9.3}{Jacobi Symbol Computation}{chapter.9}
\BOOKMARK [2][-]{subsection.9.3.1}{Jacobi Symbol}{section.9.3}
\BOOKMARK [1][-]{section.9.4}{Modular Inverse}{chapter.9}
\BOOKMARK [2][-]{subsection.9.4.1}{General Case}{section.9.4}
\BOOKMARK [1][-]{section.9.5}{Primality Tests}{chapter.9}
\BOOKMARK [2][-]{subsection.9.5.1}{Trial Division}{section.9.5}
\BOOKMARK [2][-]{subsection.9.5.2}{The Fermat Test}{section.9.5}
\BOOKMARK [2][-]{subsection.9.5.3}{The Miller-Rabin Test}{section.9.5}

Added libtommath/tommath.pdf.

cannot compute difference between binary files

Added libtommath/tommath.src.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
\usepackage{color}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{layout}
\def\union{\cup}
\def\intersect{\cap}
\def\getsrandom{\stackrel{\rm R}{\gets}}
\def\cross{\times}
\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
\def\catn{$\|$}
\def\divides{\hspace{0.3em} | \hspace{0.3em}}
\def\nequiv{\not\equiv}
\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
\def\lcm{{\rm lcm}}
\def\gcd{{\rm gcd}}
\def\log{{\rm log}}
\def\ord{{\rm ord}}
\def\abs{{\mathit abs}}
\def\rep{{\mathit rep}}
\def\mod{{\mathit\ mod\ }}
\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
\def\Or{{\rm\ or\ }}
\def\And{{\rm\ and\ }}
\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
\def\implies{\Rightarrow}
\def\undefined{{\rm ``undefined"}}
\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
\let\oldphi\phi
\def\phi{\varphi}
\def\Pr{{\rm Pr}}
\newcommand{\str}[1]{{\mathbf{#1}}}
\def\F{{\mathbb F}}
\def\N{{\mathbb N}}
\def\Z{{\mathbb Z}}
\def\R{{\mathbb R}}
\def\C{{\mathbb C}}
\def\Q{{\mathbb Q}}
\definecolor{DGray}{gray}{0.5}
\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\frontmatter
\pagestyle{empty}
\title{Multi--Precision Math}
\author{\mbox{
%\begin{small}
\begin{tabular}{c}
Tom St Denis \\
Algonquin College \\
\\
Mads Rasmussen \\
Open Communications Security \\
\\
Greg Rose \\
QUALCOMM Australia \\
\end{tabular}
%\end{small}
}
}
\maketitle
This text has been placed in the public domain.  This text corresponds to the v0.39 release of the 
LibTomMath project.

\begin{alltt}
Tom St Denis
111 Banning Rd
Ottawa, Ontario
K2L 1C3
Canada

Phone: 1-613-836-3160
Email: [email protected]
\end{alltt}

This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} 
{\em book} macro package and the Perl {\em booker} package.

\tableofcontents
\listoffigures
\chapter*{Prefaces}
When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.  
They ask why I did it and especially why I continue to work on them for free.  The best I can explain it is ``Because I can.''  
Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which 
perhaps explains it better.  I am the first to admit there is not anything that special with what I have done.  Perhaps
others can see that too and then we would have a society to be proud of.  My LibTom projects are what I am doing to give 
back to society in the form of tools and knowledge that can help others in their endeavours.

I started writing this book because it was the most logical task to further my goal of open academia.  The LibTomMath source
code itself was written to be easy to follow and learn from.  There are times, however, where pure C source code does not
explain the algorithms properly.  Hence this book.  The book literally starts with the foundation of the library and works
itself outwards to the more complicated algorithms.  The use of both pseudo--code and verbatim source code provides a duality
of ``theory'' and ``practice'' that the computer science students of the world shall appreciate.  I never deviate too far
from relatively straightforward algebra and I hope that this book can be a valuable learning asset.

This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora
of kind people donating their time, resources and kind words to help support my work.  Writing a text of significant
length (along with the source code) is a tiresome and lengthy process.  Currently the LibTom project is four years old,
comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material.  People like Mads and Greg 
were there at the beginning to encourage me to work well.  It is amazing how timely validation from others can boost morale to 
continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.  

To my many friends whom I have met through the years I thank you for the good times and the words of encouragement.  I hope I
honour your kind gestures with this project.

Open Source.  Open Academia.  Open Minds.

\begin{flushright} Tom St Denis \end{flushright}

\newpage
I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also 
contribute to educate others facing the problem of having to handle big number mathematical calculations.

This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of 
how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about 
the layout and language used.

I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the 
practical aspects of cryptography. 

Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a 
great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up 
multiple precision calculations is often very important since we deal with outdated machine architecture where modular 
reductions, for example, become painfully slow.

This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks 
themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''

\begin{flushright}
Mads Rasmussen

S\~{a}o Paulo - SP

Brazil
\end{flushright}

\newpage
It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about 
Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not 
really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.

At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the 
sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. 
Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.

When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, 
and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close 
friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, 
and I'm pleased to be involved with it.

\begin{flushright}
Greg Rose, Sydney, Australia, June 2003. 
\end{flushright}

\mainmatter
\pagestyle{headings}
\chapter{Introduction}
\section{Multiple Precision Arithmetic}

\subsection{What is Multiple Precision Arithmetic?}
When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
raise or lower the precision of the numbers we are dealing with.  For example, in decimal we almost immediate can 
reason that $7$ times $6$ is $42$.  However, $42$ has two digits of precision as opposed to one digit we started with.  
Further multiplications of say $3$ result in a larger precision result $126$.  In these few examples we have multiple 
precisions for the numbers we are working with.  Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
 of algorithms can be designed to accomodate them.  

By way of comparison a fixed or single precision operation would lose precision on various operations.  For example, in
the decimal system with fixed precision $6 \cdot 7 = 2$.

Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
schools to manually add, subtract, multiply and divide.  

\subsection{The Need for Multiple Precision Arithmetic}
The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
of public-key cryptography algorithms.   Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require 
integers of significant magnitude to resist known cryptanalytic attacks.  For example, at the time of this writing a 
typical RSA modulus would be at least greater than $10^{309}$.  However, modern programming languages such as ISO C \cite{ISOC} and 
Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{|r|c|}
\hline \textbf{Data Type} & \textbf{Range} \\
\hline char  & $-128 \ldots 127$ \\
\hline short & $-32768 \ldots 32767$ \\
\hline long  & $-2147483648 \ldots 2147483647$ \\
\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
\hline
\end{tabular}
\end{center}
\caption{Typical Data Types for the C Programming Language}
\label{fig:ISOC}
\end{figure}

The largest data type guaranteed to be provided by the ISO C programming 
language\footnote{As per the ISO C standard.  However, each compiler vendor is allowed to augment the precision as they 
see fit.}  can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is 
insufficient to accomodate the magnitude required for the problem at hand.  An RSA modulus of magnitude $10^{19}$ could be 
trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, 
rendering any protocol based on the algorithm insecure.  Multiple precision algorithms solve this very problem by 
extending the range of representable integers while using single precision data types.

Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic 
primitives.  Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in 
various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient.  In fact, several 
major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and 
deployment of efficient algorithms.

However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.  
Another auxiliary use of multiple precision integers is high precision floating point data types.  
The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.  
Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE.  Since IEEE 
floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small 
(\textit{23, 48 and 64 bits}).  The mantissa is merely an integer and a multiple precision integer could be used to create
a mantissa of much larger precision than hardware alone can efficiently support.  This approach could be useful where 
scientific applications must minimize the total output error over long calculations.

Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.

\subsection{Benefits of Multiple Precision Arithmetic}
\index{precision}
The benefit of multiple precision representations over single or fixed precision representations is that 
no precision is lost while representing the result of an operation which requires excess precision.  For example, 
the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully.  A multiple 
precision algorithm would augment the precision of the destination to accomodate the result while a single precision system 
would truncate excess bits to maintain a fixed level of precision.

It is possible to implement algorithms which require large integers with fixed precision algorithms.  For example, elliptic
curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum 
size the system will ever need.  Such an approach can lead to vastly simpler algorithms which can accomodate the 
integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard 
processor has an 8 bit accumulator.}.  However, as efficient as such an approach may be, the resulting source code is not
normally very flexible.  It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.

Multiple precision algorithms have the most overhead of any style of arithmetic.  For the the most part the 
overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
platforms.  However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the 
inputs.  That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input 
without the designer's explicit forethought.  This leads to lower cost of ownership for the code as it only has to 
be written and tested once.

\section{Purpose of This Text}
The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.  
That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' 
elements that are neglected by authors of other texts on the subject.  Several well reknowned texts \cite{TAOCPV2,HAC} 
give considerably detailed explanations of the theoretical aspects of algorithms and often very little information 
regarding the practical implementation aspects.  

In most cases how an algorithm is explained and how it is actually implemented are two very different concepts.  For 
example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple 
algorithm for performing multiple precision integer addition.  However, the description lacks any discussion concerning 
the fact that the two integer inputs may be of differing magnitudes.  As a result the implementation is not as simple
as the text would lead people to believe.  Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not 
discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).

Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers 
and fast modular inversion, which we consider practical oversights.  These optimal algorithms are vital to achieve 
any form of useful performance in non-trivial applications.  

To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
package.  As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used 
to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field 
tested and work very well.  The LibTomMath library is freely available on the Internet for all uses and this text 
discusses a very large portion of the inner workings of the library.

The algorithms that are presented will always include at least one ``pseudo-code'' description followed 
by the actual C source code that implements the algorithm.  The pseudo-code can be used to implement the same 
algorithm in other programming languages as the reader sees fit.  

This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch.  Showing
the reader how the algorithms fit together as well as where to start on various taskings.  

\section{Discussion and Notation}
\subsection{Notation}
A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$.  The elements of the array $x$ are said to be the radix $\beta$ digits 
of the integer.  For example, $x = (1,2,3)_{10}$ would represent the integer 
$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.  

\index{mp\_int}
The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well 
as auxilary data required to manipulate the data.  These additional members are discussed further in section 
\ref{sec:MPINT}.  For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be 
synonymous.  When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members 
are present as well.  An expression of the type \textit{variablename.item} implies that it should evaluate to the 
member named ``item'' of the variable.  For example, a string of characters may have a member ``length'' which would 
evaluate to the number of characters in the string.  If the string $a$ equals ``hello'' then it follows that 
$a.length = 5$.  

For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
to solve a given problem.  When an algorithm is described as accepting an integer input it is assumed the input is 
a plain integer with no additional multiple-precision members.  That is, algorithms that use integers as opposed to 
mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management.  These 
algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
precision algorithm to solve the same problem.  

\subsection{Precision Notation}
The variable $\beta$ represents the radix of a single digit of a multiple precision integer and 
must be of the form $q^p$ for $q, p \in \Z^+$.  A single precision variable must be able to represent integers in 
the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range 
$0 \le x < q \beta^2$.  The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the 
carry.  Since all modern computers are binary, it is assumed that $q$ is two.

\index{mp\_digit} \index{mp\_word}
Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent 
a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type.  In 
several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.  
For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to 
the $j$'th digit of a double precision array.  Whenever an expression is to be assigned to a double precision
variable it is assumed that all single precision variables are promoted to double precision during the evaluation.  
Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
precision data type.

For example, if $\beta = 10^2$ a single precision data type may represent a value in the 
range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$.  Let
$a = 23$ and $b = 49$ represent two single precision variables.  The single precision product shall be written
as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
In this particular case, $\hat c = 1127$ and $c = 127$.  The most significant digit of the product would not fit 
in a single precision data type and as a result $c \ne \hat c$.  

\subsection{Algorithm Inputs and Outputs}
Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
as indicated.  The only exception to this rule is when variables have been indicated to be of type mp\_int.  This 
distinction is important as scalars are often used as array indicies and various other counters.  

\subsection{Mathematical Expressions}
The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression 
itself.  For example, $\lfloor 5.7 \rfloor = 5$.  Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
rounded to an integer not less than the expression itself.  For example, $\lceil 5.1 \rceil = 6$.  Typically when 
the $/$ division symbol is used the intention is to perform an integer division with truncation.  For example, 
$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity.  When an expression is written as a 
fraction a real value division is implied, for example ${5 \over 2} = 2.5$.  

The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
of the integer.  For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.  

\subsection{Work Effort}
\index{big-Oh}
To measure the efficiency of the specified algorithms, a modified big-Oh notation is used.  In this system all 
single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.  
That is a single precision addition, multiplication and division are assumed to take the same time to 
complete.  While this is generally not true in practice, it will simplify the discussions considerably.

Some algorithms have slight advantages over others which is why some constants will not be removed in 
the notation.  For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a 
baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work.  In standard big-Oh notation these 
would both be said to be equivalent to $O(n^2)$.  However, 
in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small.  As a 
result small constant factors in the work effort will make an observable difference in algorithm efficiency.

All of the algorithms presented in this text have a polynomial time work level.  That is, of the form 
$O(n^k)$ for $n, k \in \Z^{+}$.  This will help make useful comparisons in terms of the speed of the algorithms and how 
various optimizations will help pay off in the long run.

\section{Exercises}
Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
the discussion at hand.  These exercises are not designed to be prize winning problems, but instead to be thought 
provoking.  Wherever possible the problems are forward minded, stating problems that will be answered in subsequent 
chapters.  The reader is encouraged to finish the exercises as they appear to get a better understanding of the 
subject material.  

That being said, the problems are designed to affirm knowledge of a particular subject matter.  Students in particular
are encouraged to verify they can answer the problems correctly before moving on.

Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
the problem.  However, unlike \cite{TAOCPV2} the problems do not get nearly as hard.  The scoring of these 
exercises ranges from one (the easiest) to five (the hardest).  The following table sumarizes the 
scoring system used.

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|l|}
\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
                            & minutes to solve.  Usually does not involve much computer time \\
                            & to solve. \\
\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
                     & time usage.  Usually requires a program to be written to \\
                     & solve the problem. \\
\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
                     & of work.  Usually involves trivial research and development of \\
                     & new theory from the perspective of a student. \\
\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
                     & of work and research, the solution to which will demonstrate \\
                     & a higher mastery of the subject matter. \\
\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
                     & novice to solve.  Solutions to these problems will demonstrate a \\
                     & complete mastery of the given subject. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Exercise Scoring System}
\end{figure}

Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
devising new theory.  These problems are quick tests to see if the material is understood.  Problems at the second level 
are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer.  These
two levels are essentially entry level questions.  

Problems at the third level are meant to be a bit more difficult than the first two levels.  The answer is often 
fairly obvious but arriving at an exacting solution requires some thought and skill.  These problems will almost always 
involve devising a new algorithm or implementing a variation of another algorithm previously presented.  Readers who can
answer these questions will feel comfortable with the concepts behind the topic at hand.

Problems at the fourth level are meant to be similar to those of the level three questions except they will require 
additional research to be completed.  The reader will most likely not know the answer right away, nor will the text provide 
the exact details of the answer until a subsequent chapter.  

Problems at the fifth level are meant to be the hardest 
problems relative to all the other problems in the chapter.  People who can correctly answer fifth level problems have a 
mastery of the subject matter at hand.

Often problems will be tied together.  The purpose of this is to start a chain of thought that will be discussed in future chapters.  The reader
is encouraged to answer the follow-up problems and try to draw the relevance of problems.

\section{Introduction to LibTomMath}

\subsection{What is LibTomMath?}
LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C.  By portable it 
is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on 
any given platform.  

The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such 
as the Gameboy Advance.  The library is designed to contain enough functionality to be able to develop applications such 
as public key cryptosystems and still maintain a relatively small footprint.

\subsection{Goals of LibTomMath}

Libraries which obtain the most efficiency are rarely written in a high level programming language such as C.  However, 
even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the 
library.  Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM 
processors.  Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window 
exponentiation and Montgomery reduction have been provided to make the library more efficient.  

Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface 
(\textit{API}) has been kept as simple as possible.  Often generic place holder routines will make use of specialized 
algorithms automatically without the developer's specific attention.  One such example is the generic multiplication 
algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication 
based on the magnitude of the inputs and the configuration of the library.  

Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project.  Ideally the library should 
be source compatible with another popular library which makes it more attractive for developers to use.  In this case the
MPI library was used as a API template for all the basic functions.  MPI was chosen because it is another library that fits 
in the same niche as LibTomMath.  Even though LibTomMath uses MPI as the template for the function names and argument 
passing conventions, it has been written from scratch by Tom St Denis.

The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' 
library exists which can be used to teach computer science students how to perform fast and reliable multiple precision 
integer arithmetic.  To this end the source code has been given quite a few comments and algorithm discussion points.  

\section{Choice of LibTomMath}
LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
for more worthy reasons.  Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL 
\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for 
reasons that will be explained in the following sub-sections.

\subsection{Code Base}
The LibTomMath code base is all portable ISO C source code.  This means that there are no platform dependent conditional
segments of code littered throughout the source.  This clean and uncluttered approach to the library means that a
developer can more readily discern the true intent of a given section of source code without trying to keep track of
what conditional code will be used.

The code base of LibTomMath is well organized.  Each function is in its own separate source code file 
which allows the reader to find a given function very quickly.  On average there are $76$ lines of code per source
file which makes the source very easily to follow.  By comparison MPI and LIP are single file projects making code tracing
very hard.  GMP has many conditional code segments which also hinder tracing.  

When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
 which is fairly small compared to GMP (over $250$KiB).  LibTomMath is slightly larger than MPI (which compiles to about 
$50$KiB) but LibTomMath is also much faster and more complete than MPI.

\subsection{API Simplicity}
LibTomMath is designed after the MPI library and shares the API design.  Quite often programs that use MPI will build 
with LibTomMath without change. The function names correlate directly to the action they perform.  Almost all of the 
functions share the same parameter passing convention.  The learning curve is fairly shallow with the API provided 
which is an extremely valuable benefit for the student and developer alike.  

The LIP library is an example of a library with an API that is awkward to work with.  LIP uses function names that are often ``compressed'' to 
illegible short hand.  LibTomMath does not share this characteristic.  

The GMP library also does not return error codes.  Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
are signaled to the host application.  This happens to be the fastest approach but definitely not the most versatile.  In
effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely 
undersireable in many situations.

\subsection{Optimizations}
While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring.  GMP 
and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations.  GMP lacks a few
of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
only had Barrett and Montgomery modular reduction algorithms.}.  

LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
exponentiation.  In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually  
slower than the best libraries such as GMP and OpenSSL by only a small factor.

\subsection{Portability and Stability}
LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler 
(\textit{GCC}).  This means that without changes the library will build without configuration or setting up any 
variables.  LIP and MPI will build ``out of the box'' as well but have numerous known bugs.  Most notably the author of 
MPI has recently stopped working on his library and LIP has long since been discontinued.  

GMP requires a configuration script to run and will not build out of the box.   GMP and LibTomMath are still in active
development and are very stable across a variety of platforms.

\subsection{Choice}
LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
the case study of this text.  Various source files from the LibTomMath project will be included within the text.  However, 
the reader is encouraged to download their own copy of the library to actually be able to work with the library.  

\chapter{Getting Started}
\section{Library Basics}
The trick to writing any useful library of source code is to build a solid foundation and work outwards from it.  First, 
a problem along with allowable solution parameters should be identified and analyzed.  In this particular case the 
inability to accomodate multiple precision integers is the problem.  Futhermore, the solution must be written
as portable source code that is reasonably efficient across several different computer platforms.

After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.  
That is, to implement the lowest level dependencies first and work towards the most abstract functions last.  For example, 
before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
By building outwards from a base foundation instead of using a parallel design methodology the resulting project is 
highly modular.  Being highly modular is a desirable property of any project as it often means the resulting product
has a small footprint and updates are easy to perform.  

Usually when I start a project I will begin with the header files.  I define the data types I think I will need and 
prototype the initial functions that are not dependent on other functions (within the library).  After I 
implement these base functions I prototype more dependent functions and implement them.   The process repeats until
I implement all of the functions I require.  For example, in the case of LibTomMath I implemented functions such as 
mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod().  As an example as to 
why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the 
dependent function mp\_exptmod() was written.  Adding the new multiplication algorithms did not require changes to the 
mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development 
for new algorithms.  This methodology allows new algorithms to be tested in a complete framework with relative ease.

FIGU,design_process,Design Flow of the First Few Original LibTomMath Functions.

Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
the source code.  For example, one day I may audit the multipliers and the next day the polynomial basis functions.  

It only makes sense to begin the text with the preliminary data types and support algorithms required as well.  
This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.

\section{What is a Multiple Precision Integer?}
Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot 
be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is 
to use fixed precision data types to create and manipulate multiple precision integers which may represent values 
that are very large.  

As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits.  In the decimal system
the largest single digit value is $9$.  However, by concatenating digits together larger numbers may be represented.  Newly prepended digits 
(\textit{to the left}) are said to be in a different power of ten column.  That is, the number $123$ can be described as having a $1$ in the hundreds 
column, $2$ in the tens column and $3$ in the ones column.  Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$.  Computer based 
multiple precision arithmetic is essentially the same concept.  Larger integers are represented by adjoining fixed 
precision computer words with the exception that a different radix is used.

What most people probably do not think about explicitly are the various other attributes that describe a multiple precision 
integer.  For example, the integer $154_{10}$ has two immediately obvious properties.  First, the integer is positive, 
that is the sign of this particular integer is positive as opposed to negative.  Second, the integer has three digits in 
its representation.  There is an additional property that the integer posesses that does not concern pencil-and-paper 
arithmetic.  The third property is how many digits placeholders are available to hold the integer.  

The human analogy of this third property is ensuring there is enough space on the paper to write the integer.  For example,
if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.  
Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
will not exceed the allowed boundaries.  These three properties make up what is known as a multiple precision 
integer or mp\_int for short.  

\subsection{The mp\_int Structure}
\label{sec:MPINT}
The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer.  The ISO C standard does not provide for 
any such data type but it does provide for making composite data types known as structures.  The following is the structure definition 
used within LibTomMath.

\index{mp\_int}
\begin{figure}[here]
\begin{center}
\begin{small}
%\begin{verbatim}
\begin{tabular}{|l|}
\hline
typedef struct \{ \\
\hspace{3mm}int used, alloc, sign;\\
\hspace{3mm}mp\_digit *dp;\\
\} \textbf{mp\_int}; \\
\hline
\end{tabular}
%\end{verbatim}
\end{small}
\caption{The mp\_int Structure}
\label{fig:mpint}
\end{center}
\end{figure}

The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.

\begin{enumerate}
\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
a given integer.  The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.  

\item The \textbf{alloc} parameter denotes how 
many digits are available in the array to use by functions before it has to increase in size.  When the \textbf{used} count 
of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the 
array to accommodate the precision of the result.  

\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple 
precision integer.  It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits.  The array is maintained in a least 
significant digit order.  As a pencil and paper analogy the array is organized such that the right most digits are stored
first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array.  For example, 
if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then 
it would represent the integer $a + b\beta + c\beta^2 + \ldots$  

\index{MP\_ZPOS} \index{MP\_NEG}
\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).  
\end{enumerate}

\subsubsection{Valid mp\_int Structures}
Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.  
The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().

\begin{enumerate}
\item The value of \textbf{alloc} may not be less than one.  That is \textbf{dp} always points to a previously allocated
array of digits.
\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero.  That is, 
leading zero digits in the most significant positions must be trimmed.
   \begin{enumerate}
   \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
   \end{enumerate}
\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; 
this represents the mp\_int value of zero.
\end{enumerate}

\section{Argument Passing}
A convention of argument passing must be adopted early on in the development of any library.  Making the function 
prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.  
In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int 
structures.  That means that the source (input) operands are placed on the left and the destination (output) on the right.   
Consider the following examples.

\begin{verbatim}
   mp_mul(&a, &b, &c);   /* c = a * b */
   mp_add(&a, &b, &a);   /* a = a + b */
   mp_sqr(&a, &b);       /* b = a * a */
\end{verbatim}

The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
functions and make sense of them.  For example, the first function would read ``multiply a and b and store in c''.

Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
of assignment expressions.  That is, the destination (output) is on the left and arguments (inputs) are on the right.  In 
truth, it is entirely a matter of preference.  In the case of LibTomMath the convention from the MPI library has been 
adopted.  

Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a 
destination.  For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$.  This is an important 
feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.  
However, to implement this feature specific care has to be given to ensure the destination is not modified before the 
source is fully read.

\section{Return Values}
A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them 
to the caller.  By catching runtime errors a library can be guaranteed to prevent undefined behaviour.  However, the end 
developer can still manage to cause a library to crash.  For example, by passing an invalid pointer an application may
fault by dereferencing memory not owned by the application.

In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for 
instance) and memory allocation errors.  It will not check that the mp\_int passed to any function is valid nor 
will it check pointers for validity.  Any function that can cause a runtime error will return an error code as an 
\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).

\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
\begin{figure}[here]
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Value} & \textbf{Meaning} \\
\hline \textbf{MP\_OKAY} & The function was successful \\
\hline \textbf{MP\_VAL}  & One of the input value(s) was invalid \\
\hline \textbf{MP\_MEM}  & The function ran out of heap memory \\
\hline
\end{tabular}
\end{center}
\caption{LibTomMath Error Codes}
\label{fig:errcodes}
\end{figure}

When an error is detected within a function it should free any memory it allocated, often during the initialization of
temporary mp\_ints, and return as soon as possible.  The goal is to leave the system in the same state it was when the 
function was called.  Error checking with this style of API is fairly simple.

\begin{verbatim}
   int err;
   if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
      printf("Error: %s\n", mp_error_to_string(err));
      exit(EXIT_FAILURE);
   }
\end{verbatim}

The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use.  Not all errors are fatal 
and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.

\section{Initialization and Clearing}
The logical starting point when actually writing multiple precision integer functions is the initialization and 
clearing of the mp\_int structures.  These two algorithms will be used by the majority of the higher level algorithms.

Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
the integer.  Often it is optimal to allocate a sufficiently large pre-set number of digits even though
the initial integer will represent zero.  If only a single digit were allocated quite a few subsequent re-allocations
would occur when operations are performed on the integers.  There is a tradeoff between how many default digits to allocate
and how many re-allocations are tolerable.  Obviously allocating an excessive amount of digits initially will waste 
memory and become unmanageable.  

If the memory for the digits has been successfully allocated then the rest of the members of the structure must
be initialized.  Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
to zero.  The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.

\subsection{Initializing an mp\_int}
An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
structure are set to valid values.  The mp\_init algorithm will perform such an action.

\index{mp\_init}
\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Allocate memory and initialize $a$ to a known valid mp\_int state.  \\
\hline \\
1.  Allocate memory for \textbf{MP\_PREC} digits. \\
2.  If the allocation failed return(\textit{MP\_MEM}) \\
3.  for $n$ from $0$ to $MP\_PREC - 1$ do  \\
\hspace{3mm}3.1  $a_n \leftarrow 0$\\
4.  $a.sign \leftarrow MP\_ZPOS$\\
5.  $a.used \leftarrow 0$\\
6.  $a.alloc \leftarrow MP\_PREC$\\
7.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init}
\end{figure}

\textbf{Algorithm mp\_init.}
The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
manipulte it.  It is assumed that the input may not have had any of its members previously initialized which is certainly
a valid assumption if the input resides on the stack.  

Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
the digits is allocated.  If this fails the function returns before setting any of the other members.  The \textbf{MP\_PREC} 
name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} 
used to dictate the minimum precision of newly initialized mp\_int integers.  Ideally, it is at least equal to the smallest
precision number you'll be working with.

Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
heap operations later functions will have to perform in the future.  If \textbf{MP\_PREC} is set correctly the slack 
memory and the number of heap operations will be trivial.

Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
\textbf{alloc} members initialized.  This ensures that the mp\_int will always represent the default state of zero regardless
of the original condition of the input.

\textbf{Remark.}
This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
when the ``to'' keyword is placed between two expressions.  For example, ``for $a$ from $b$ to $c$ do'' means that
a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$.  In each
iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$.  If $b > c$ occured
the loop would not iterate.  By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate 
decrementally.

EXAM,bn_mp_init.c

One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure.  It 
is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack.  The 
call to mp\_init() is used only to initialize the members of the structure to a known default state.  

Here we see (line @23,XMALLOC@) the memory allocation is performed first.  This allows us to exit cleanly and quickly
if there is an error.  If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
was a memory error.  The function XMALLOC is what actually allocates the memory.  Technically XMALLOC is not a function
but a macro defined in ``tommath.h``.  By default, XMALLOC will evaluate to malloc() which is the C library's built--in
memory allocation routine.

In order to assure the mp\_int is in a known state the digits must be set to zero.  On most platforms this could have been
accomplished by using calloc() instead of malloc().  However,  to correctly initialize a integer type to a given value in a 
portable fashion you have to actually assign the value.  The for loop (line @28,for@) performs this required
operation.

After the memory has been successfully initialized the remainder of the members are initialized 
(lines @29,used@ through @31,sign@) to their respective default states.  At this point the algorithm has succeeded and
a success code is returned to the calling function.  If this function returns \textbf{MP\_OKAY} it is safe to assume the 
mp\_int structure has been properly initialized and is safe to use with other functions within the library.  

\subsection{Clearing an mp\_int}
When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be 
returned to the application's memory pool with the mp\_clear algorithm.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clear}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  The memory for $a$ shall be deallocated.  \\
\hline \\
1.  If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $a_n \leftarrow 0$ \\
3.  Free the memory allocated for the digits of $a$. \\
4.  $a.used \leftarrow 0$ \\
5.  $a.alloc \leftarrow 0$ \\
6.  $a.sign \leftarrow MP\_ZPOS$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_clear}
\end{figure}

\textbf{Algorithm mp\_clear.}
This algorithm accomplishes two goals.  First, it clears the digits and the other mp\_int members.  This ensures that 
if a developer accidentally re-uses a cleared structure it is less likely to cause problems.  The second goal
is to free the allocated memory.

The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
algorithm will not try to free the memory multiple times.  Cleared mp\_ints are detectable by having a pre-defined invalid 
digit pointer \textbf{dp} setting.

Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.

EXAM,bn_mp_clear.c

The algorithm only operates on the mp\_int if it hasn't been previously cleared.  The if statement (line @23,a->dp != NULL@)
checks to see if the \textbf{dp} member is not \textbf{NULL}.  If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
\textbf{NULL} in which case the if statement will evaluate to true.

The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit.  Similar to mp\_init()
the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.  

The digits are deallocated off the heap via the XFREE macro.  Similar to XMALLOC the XFREE macro actually evaluates to
a standard C library function.  In this case the free() function.  Since free() only deallocates the memory the pointer
still has to be reset to \textbf{NULL} manually (line @33,NULL@).  

Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@).

\section{Maintenance Algorithms}

The previous sections describes how to initialize and clear an mp\_int structure.  To further support operations
that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
able to augment the precision of an mp\_int and 
initialize mp\_ints with differing initial conditions.  

These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
algorithms such as addition, multiplication and modular exponentiation.

\subsection{Augmenting an mp\_int's Precision}
When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire 
result of an operation without loss of precision.  Quite often the size of the array given by the \textbf{alloc} member 
is large enough to simply increase the \textbf{used} digit count.  However, when the size of the array is too small it 
must be re-sized appropriately to accomodate the result.  The mp\_grow algorithm will provide this functionality.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_grow}. \\
\textbf{Input}.   An mp\_int $a$ and an integer $b$. \\
\textbf{Output}.  $a$ is expanded to accomodate $b$ digits. \\
\hline \\
1.  if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
2.  $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
3.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
4.  Re-allocate the array of digits $a$ to size $v$ \\
5.  If the allocation failed then return(\textit{MP\_MEM}). \\
6.  for n from a.alloc to $v - 1$ do  \\
\hspace{+3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.alloc \leftarrow v$ \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_grow}
\end{figure}

\textbf{Algorithm mp\_grow.}
It is ideal to prevent re-allocations from being performed if they are not required (step one).  This is useful to 
prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.  

The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).  
This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.  

It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact.  This is much 
akin to how the \textit{realloc} function from the standard C library works.  Since the newly allocated digits are 
assumed to contain undefined values they are initially set to zero.

EXAM,bn_mp_grow.c

A quick optimization is to first determine if a memory re-allocation is required at all.  The if statement (line @24,alloc@) checks
if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count.  If the count is not larger than \textbf{alloc}
the function skips the re-allocation part thus saving time.

When a re-allocation is performed it is turned into an optimal request to save time in the future.  The requested digit count is
padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@).  The XREALLOC function is used
to re-allocate the memory.  As per the other functions XREALLOC is actually a macro which evaluates to realloc by default.  The realloc
function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
the re-allocation.  All	that is left is to clear the newly allocated digits and return.

Note that the re-allocation result is actually stored in a temporary pointer $tmp$.  This is to allow this function to return
an error with a valid pointer.  Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$.  That would
result in a memory leak if XREALLOC ever failed.  

\subsection{Initializing Variable Precision mp\_ints}
Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size 
of input mp\_ints to a given algorithm.  The purpose of algorithm mp\_init\_size is similar to mp\_init except that it 
will allocate \textit{at least} a specified number of digits.  

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_size}. \\
\textbf{Input}.   An mp\_int $a$ and the requested number of digits $b$. \\
\textbf{Output}.  $a$ is initialized to hold at least $b$ digits. \\
\hline \\
1.  $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
2.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
3.  Allocate $v$ digits. \\
4.  for $n$ from $0$ to $v - 1$ do \\
\hspace{3mm}4.1  $a_n \leftarrow 0$ \\
5.  $a.sign \leftarrow MP\_ZPOS$\\
6.  $a.used \leftarrow 0$\\
7.  $a.alloc \leftarrow v$\\
8.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_init\_size}
\end{figure}

\textbf{Algorithm mp\_init\_size.}
This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of 
digits allocated can be controlled by the second input argument $b$.  The input size is padded upwards so it is a 
multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits.  This padding is used to prevent trivial 
allocations from becoming a bottleneck in the rest of the algorithms.

Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero.  This 
particular algorithm is useful if it is known ahead of time the approximate size of the input.  If the approximation is
correct no further memory re-allocations are required to work with the mp\_int.

EXAM,bn_mp_init_size.c

The number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of 
\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result.  If the memory can be successfully allocated the 
mp\_int is placed in a default state representing the integer zero.  Otherwise, the error code \textbf{MP\_MEM} will be 
returned (line @27,return@).  

The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@).  The 
\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set 
to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@).  If the function 
returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the 
functions to work with.

\subsection{Multiple Integer Initializations and Clearings}
Occasionally a function will require a series of mp\_int data types to be made available simultaneously.  
The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
statement.  It is essentially a shortcut to multiple initializations.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_multi}. \\
\textbf{Input}.   Variable length array $V_k$ of mp\_int variables of length $k$. \\
\textbf{Output}.  The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
\hline \\
1.  for $n$ from 0 to $k - 1$ do \\
\hspace{+3mm}1.1.  Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
\hspace{+3mm}1.2.  If initialization failed then do \\
\hspace{+6mm}1.2.1.  for $j$ from $0$ to $n$ do \\
\hspace{+9mm}1.2.1.1.  Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
\hspace{+6mm}1.2.2.   Return(\textit{MP\_MEM}) \\
2.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_multi}
\end{figure}

\textbf{Algorithm mp\_init\_multi.}
The algorithm will initialize the array of mp\_int variables one at a time.  If a runtime error has been detected 
(\textit{step 1.2}) all of the previously initialized variables are cleared.  The goal is an ``all or nothing'' 
initialization which allows for quick recovery from runtime errors.

EXAM,bn_mp_init_multi.c

This function intializes a variable length list of mp\_int structure pointers.  However, instead of having the mp\_int
structures in an actual C array they are simply passed as arguments to the function.  This function makes use of the 
``...'' argument syntax of the C programming language.  The list is terminated with a final \textbf{NULL} argument 
appended on the right.  

The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function.  A count
$n$ of succesfully initialized mp\_int structures is maintained (line @47,n++@) such that if a failure does occur,
the algorithm can backtrack and free the previously initialized structures (lines @27,if@ to @46,}@).  


\subsection{Clamping Excess Digits}
When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of 
the function instead of checking during the computation.  For example, a multiplication of a $i$ digit number by a 
$j$ digit produces a result of at most $i + j$ digits.  It is entirely possible that the result is $i + j - 1$ 
though, with no final carry into the last position.  However, suppose the destination had to be first expanded 
(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.  
That would be a considerable waste of time since heap operations are relatively slow.

The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
terminates.  This way a single heap operation (\textit{at most}) is required.  However, if the result was not checked
there would be an excess high order zero digit.  

For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$.  The leading zero digit 
will not contribute to the precision of the result.  In fact, through subsequent operations more leading zero digits would
accumulate to the point the size of the integer would be prohibitive.  As a result even though the precision is very 
low the representation is excessively large.  

The mp\_clamp algorithm is designed to solve this very problem.  It will trim high-order zeros by decrementing the 
\textbf{used} count until a non-zero most significant digit is found.  Also in this system, zero is considered to be a 
positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to 
\textbf{MP\_ZPOS}.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clamp}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Any excess leading zero digits of $a$ are removed \\
\hline \\
1.  while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
\hspace{+3mm}1.1  $a.used \leftarrow a.used - 1$ \\
2.  if $a.used = 0$ then do \\
\hspace{+3mm}2.1  $a.sign \leftarrow MP\_ZPOS$ \\
\hline \\
\end{tabular}
\end{center}
\caption{Algorithm mp\_clamp}
\end{figure}

\textbf{Algorithm mp\_clamp.}
As can be expected this algorithm is very simple.  The loop on step one is expected to iterate only once or twice at
the most.  For example, this will happen in cases where there is not a carry to fill the last position.  Step two fixes the sign for 
when all of the digits are zero to ensure that the mp\_int is valid at all times.

EXAM,bn_mp_clamp.c

Note on line @27,while@ how to test for the \textbf{used} count is made on the left of the \&\& operator.  In the C programming
language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails.  This is 
important since if the \textbf{used} is zero the test on the right would fetch below the array.  That is obviously 
undesirable.  The parenthesis on line @28,a->used@ is used to make sure the \textbf{used} count is decremented and not
the pointer ``a''.  

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
                     & \\
$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations.  \\
                     & \\
$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
                     & encryption when $\beta = 2^{28}$.  \\
                     & \\
$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp.  What does it prevent? \\
                     & \\
$\left [ 1 \right ]$ & Give an example of when the algorithm  mp\_init\_copy might be useful. \\
                     & \\
\end{tabular}


%%%
% CHAPTER FOUR
%%%

\chapter{Basic Operations}

\section{Introduction}
In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
mp\_int structures.  This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low 
level basis of the entire library.  While these algorithm are relatively trivial it is important to understand how they
work before proceeding since these algorithms will be used almost intrinsically in the following chapters.

The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
represent.   

\section{Assigning Values to mp\_int Structures}
\subsection{Copying an mp\_int}
Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
a copy for the purposes of this text.  The copy of the mp\_int will be a separate entity that represents the same
value as the mp\_int it was copied from.  The mp\_copy algorithm provides this functionality. 

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_copy}. \\
\textbf{Input}.  An mp\_int $a$ and $b$. \\
\textbf{Output}.  Store a copy of $a$ in $b$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to $a.used$ digits.  (\textit{mp\_grow}) \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $b_{n} \leftarrow a_{n}$ \\
3.  for $n$ from $a.used$ to $b.used - 1$ do \\
\hspace{3mm}3.1  $b_{n} \leftarrow 0$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $b.sign \leftarrow a.sign$ \\
6.  return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_copy}
\end{figure}

\textbf{Algorithm mp\_copy.}
This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
represent the same integer as the mp\_int $a$.  The mp\_int $b$ shall be a complete and distinct copy of the 
mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.

If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow 
algorithm.  The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
and three).  The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
$b$.

\textbf{Remark.}  This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
text.  The error return codes of other algorithms are not explicitly checked in the pseudo-code presented.  For example, in 
step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded.  Text space is 
limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
the error code itself.  However, the C code presented will demonstrate all of the error handling logic required to 
implement the pseudo-code.

EXAM,bn_mp_copy.c

Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
mp\_int structures passed to a function are one and the same.  For this case it is optimal to return immediately without 
copying digits (line @24,a == b@).  

The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$.  If $b.alloc$ is less than
$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines @29,alloc@ to @33,}@).  In order to
simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
of the mp\_ints $a$ and $b$ respectively.  These aliases (lines @42,tmpa@ and @45,tmpb@) allow the compiler to access the digits without first dereferencing the
mp\_int pointers and then subsequently the pointer to the digits.  

After the aliases are established the digits from $a$ are copied into $b$ (lines @48,for@ to @50,}@) and then the excess 
digits of $b$ are set to zero (lines @53,for@ to @55,}@).  Both ``for'' loops make use of the pointer aliases and in 
fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits.  This optimization 
allows the alias to stay in a machine register fairly easy between the two loops.

\textbf{Remarks.}  The use of pointer aliases is an implementation methodology first introduced in this function that will
be used considerably in other functions.  Technically, a pointer alias is simply a short hand alias used to lower the 
number of pointer dereferencing operations required to access data.  For example, a for loop may resemble

\begin{alltt}
for (x = 0; x < 100; x++) \{
    a->num[4]->dp[x] = 0;
\}
\end{alltt}

This could be re-written using aliases as 

\begin{alltt}
mp_digit *tmpa;
a = a->num[4]->dp;
for (x = 0; x < 100; x++) \{
    *a++ = 0;
\}
\end{alltt}

In this case an alias is used to access the 
array of digits within an mp\_int structure directly.  It may seem that a pointer alias is strictly not required 
as a compiler may optimize out the redundant pointer operations.  However, there are two dominant reasons to use aliases.

The first reason is that most compilers will not effectively optimize pointer arithmetic.  For example, some optimizations 
may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC).  Also some optimizations may 
work for GCC and not MSVC.  As such it is ideal to find a common ground for as many compilers as possible.  Pointer 
aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code 
stands a better chance of being faster.

The second reason is that pointer aliases often can make an algorithm simpler to read.  Consider the first ``for'' 
loop of the function mp\_copy() re-written to not use pointer aliases.

\begin{alltt}
    /* copy all the digits */
    for (n = 0; n < a->used; n++) \{
      b->dp[n] = a->dp[n];
    \}
\end{alltt}

Whether this code is harder to read depends strongly on the individual.  However, it is quantifiably slightly more 
complicated as there are four variables within the statement instead of just two.

\subsubsection{Nested Statements}
Another commonly used technique in the source routines is that certain sections of code are nested.  This is used in
particular with the pointer aliases to highlight code phases.  For example, a Comba multiplier (discussed in chapter six)
will typically have three different phases.  First the temporaries are initialized, then the columns calculated and 
finally the carries are propagated.  In this example the middle column production phase will typically be nested as it
uses temporary variables and aliases the most.

The nesting also simplies the source code as variables that are nested are only valid for their scope.  As a result
the various temporary variables required do not propagate into other sections of code.


\subsection{Creating a Clone}
Another common operation is to make a local temporary copy of an mp\_int argument.  To initialize an mp\_int 
and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone.  This is 
useful within functions that need to modify an argument but do not wish to actually modify the original copy.  The 
mp\_init\_copy algorithm has been designed to help perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_copy}. \\
\textbf{Input}.   An mp\_int $a$ and $b$\\
\textbf{Output}.  $a$ is initialized to be a copy of $b$. \\
\hline \\
1.  Init $a$.  (\textit{mp\_init}) \\
2.  Copy $b$ to $a$.  (\textit{mp\_copy}) \\
3.  Return the status of the copy operation. \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_copy}
\end{figure}

\textbf{Algorithm mp\_init\_copy.}
This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it.  As 
such this algorithm will perform two operations in one step.  

EXAM,bn_mp_init_copy.c

This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}.  Note that 
\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
and \textbf{a} will be left intact.  

\section{Zeroing an Integer}
Reseting an mp\_int to the default state is a common step in many algorithms.  The mp\_zero algorithm will be the algorithm used to
perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_zero}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Zero the contents of $a$ \\
\hline \\
1.  $a.used \leftarrow 0$ \\
2.  $a.sign \leftarrow$ MP\_ZPOS \\
3.  for $n$ from 0 to $a.alloc - 1$ do \\
\hspace{3mm}3.1  $a_n \leftarrow 0$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_zero}
\end{figure}

\textbf{Algorithm mp\_zero.}
This algorithm simply resets a mp\_int to the default state.  

EXAM,bn_mp_zero.c

After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the 
\textbf{sign} variable is set to \textbf{MP\_ZPOS}.

\section{Sign Manipulation}
\subsection{Absolute Value}
With the mp\_int representation of an integer, calculating the absolute value is trivial.  The mp\_abs algorithm will compute
the absolute value of an mp\_int.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_abs}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = \vert a \vert$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  $b.sign \leftarrow MP\_ZPOS$ \\
4.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_abs}
\end{figure}

\textbf{Algorithm mp\_abs.}
This algorithm computes the absolute of an mp\_int input.  First it copies $a$ over $b$.  This is an example of an
algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful.  This allows,
for instance, the developer to pass the same mp\_int as the source and destination to this function without addition 
logic to handle it.

EXAM,bn_mp_abs.c

This fairly trivial algorithm first eliminates non--required duplications (line @27,a != b@) and then sets the
\textbf{sign} flag to \textbf{MP\_ZPOS}.

\subsection{Integer Negation}
With the mp\_int representation of an integer, calculating the negation is also trivial.  The mp\_neg algorithm will compute
the negative of an mp\_int input.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_neg}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = -a$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
4.  If $a.sign = MP\_ZPOS$ then do \\
\hspace{3mm}4.1  $b.sign = MP\_NEG$. \\
5.  else do \\
\hspace{3mm}5.1  $b.sign = MP\_ZPOS$. \\
6.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_neg}
\end{figure}

\textbf{Algorithm mp\_neg.}
This algorithm computes the negation of an input.  First it copies $a$ over $b$.  If $a$ has no used digits then
the algorithm returns immediately.  Otherwise it flips the sign flag and stores the result in $b$.  Note that if 
$a$ had no digits then it must be positive by definition.  Had step three been omitted then the algorithm would return
zero as negative.

EXAM,bn_mp_neg.c

Like mp\_abs() this function avoids non--required duplications (line @21,a != b@) and then sets the sign.  We
have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}.  If the mp\_int is zero
than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.

\section{Small Constants}
\subsection{Setting Small Constants}
Often a mp\_int must be set to a relatively small value such as $1$ or $2$.  For these cases the mp\_set algorithm is useful.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set}. \\
\textbf{Input}.   An mp\_int $a$ and a digit $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}). \\
2.  $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
3.  $a.used \leftarrow  \left \lbrace \begin{array}{ll}
                              1 &  \mbox{if }a_0 > 0 \\
                              0 &  \mbox{if }a_0 = 0 
                              \end{array} \right .$ \\
\hline                              
\end{tabular}
\end{center}
\caption{Algorithm mp\_set}
\end{figure}

\textbf{Algorithm mp\_set.}
This algorithm sets a mp\_int to a small single digit value.  Step number 1 ensures that the integer is reset to the default state.  The
single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.

EXAM,bn_mp_set.c

First we zero (line @21,mp_zero@) the mp\_int to make sure that the other members are initialized for a 
small positive constant.  mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
is zero.  Next we set the digit and reduce it modulo $\beta$ (line @22,MP_MASK@).  After this step we have to 
check if the resulting digit is zero or not.  If it is not then we set the \textbf{used} count to one, otherwise
to zero.

We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with 
$2^k - 1$ will perform the same operation.

One important limitation of this function is that it will only set one digit.  The size of a digit is not fixed, meaning source that uses 
this function should take that into account.  Only trivially small constants can be set using this function.

\subsection{Setting Large Constants}
To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal.  It accepts a ``long''
data type as input and will always treat it as a 32-bit integer.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set\_int}. \\
\textbf{Input}.   An mp\_int $a$ and a ``long'' integer $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}) \\
2.  for $n$ from 0 to 7 do \\
\hspace{3mm}2.1  $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
\hspace{3mm}2.2  $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
\hspace{3mm}2.3  $a_0 \leftarrow a_0 + u$ \\
\hspace{3mm}2.4  $a.used \leftarrow a.used + 1$ \\
3.  Clamp excess used digits (\textit{mp\_clamp}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_set\_int}
\end{figure}

\textbf{Algorithm mp\_set\_int.}
The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the 
mp\_int.  Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions.  In step 2.2 the
next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is 
incremented to reflect the addition.  The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
zero digits used and the newly added four bits would be ignored.

Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.

EXAM,bn_mp_set_int.c

This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes.  The weird
addition on line @38,a->used@ ensures that the newly added in bits are added to the number of digits.  While it may not 
seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line @27,mp_mul_2d@ 
as well as the  call to mp\_clamp() on line @40,mp_clamp@.  Both functions will clamp excess leading digits which keeps 
the number of used digits low.

\section{Comparisons}
\subsection{Unsigned Comparisions}
Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers.  For example,
to compare $1,234$ to $1,264$ the digits are extracted by their positions.  That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude 
positions.  If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.  

The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
mp\_int variables alone.  It will ignore the sign of the two inputs.  Such a function is useful when an absolute comparison is required or if the 
signs are known to agree in advance.

To facilitate working with the results of the comparison functions three constants are required.  

\begin{figure}[here]
\begin{center}
\begin{tabular}{|r|l|}
\hline \textbf{Constant} & \textbf{Meaning} \\
\hline \textbf{MP\_GT} & Greater Than \\
\hline \textbf{MP\_EQ} & Equal To \\
\hline \textbf{MP\_LT} & Less Than \\
\hline
\end{tabular}
\end{center}
\caption{Comparison Return Codes}
\end{figure}

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp\_mag}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$.  \\
\textbf{Output}.  Unsigned comparison results ($a$ to the left of $b$). \\
\hline \\
1.  If $a.used > b.used$ then return(\textit{MP\_GT}) \\
2.  If $a.used < b.used$ then return(\textit{MP\_LT}) \\
3.  for n from $a.used - 1$ to 0 do \\
\hspace{+3mm}3.1  if $a_n > b_n$ then return(\textit{MP\_GT}) \\
\hspace{+3mm}3.2  if $a_n < b_n$ then return(\textit{MP\_LT}) \\
4.  Return(\textit{MP\_EQ}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp\_mag}
\end{figure}

\textbf{Algorithm mp\_cmp\_mag.}
By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$.  The first two steps compare the number of digits used in both $a$ and $b$.  
Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.  
If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.  

By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
the zero'th digit.  If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.

EXAM,bn_mp_cmp_mag.c

The two if statements (lines @24,if@ and @28,if@) compare the number of digits in the two inputs.  These two are 
performed before all of the digits are compared since it is a very cheap test to perform and can potentially save 
considerable time.  The implementation given is also not valid without those two statements.  $b.alloc$ may be 
smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.



\subsection{Signed Comparisons}
Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}).  Based on an unsigned magnitude 
comparison a trivial signed comparison algorithm can be written.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  Signed Comparison Results ($a$ to the left of $b$) \\
\hline \\
1.  if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
2.  if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
3.  if $a.sign = MP\_NEG$ then \\
\hspace{+3mm}3.1  Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
4   Otherwise \\
\hspace{+3mm}4.1  Return the unsigned comparison of $a$ and $b$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp}
\end{figure}

\textbf{Algorithm mp\_cmp.}
The first two steps compare the signs of the two inputs.  If the signs do not agree then it can return right away with the appropriate 
comparison code.  When the signs are equal the digits of the inputs must be compared to determine the correct result.  In step 
three the unsigned comparision flips the order of the arguments since they are both negative.  For instance, if $-a > -b$ then 
$\vert a \vert < \vert b \vert$.  Step number four will compare the two when they are both positive.

EXAM,bn_mp_cmp.c

The two if statements (lines @22,if@ and @26,if@) perform the initial sign comparison.  If the signs are not the equal then which ever
has the positive sign is larger.   The inputs are compared (line @30,if@) based on magnitudes.  If the signs were both 
negative then the unsigned comparison is performed in the opposite direction (line @31,mp_cmp_mag@).  Otherwise, the signs are assumed to 
be both positive and a forward direction unsigned comparison is performed.

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
                     & \\
$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits  \\
                     & of two random digits (of equal magnitude) before a difference is found. \\
                     & \\
$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based  \\
                     & on the observations made in the previous problem. \\
                     &
\end{tabular}

\chapter{Basic Arithmetic}
\section{Introduction}
At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been 
established.  The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms.  These 
algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms.  It is very important 
that these algorithms are highly optimized.  On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms 
which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.  

MARK,SHIFTS
All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right 
logical shifts respectively.  A logical shift is analogous to sliding the decimal point of radix-10 representations.  For example, the real 
number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).  
Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.  
For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.

One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
from the number.  For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$.  However, with a logical shift the 
result is $110_2$.  

\section{Addition and Subtraction}
In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus.  For example, with 32-bit integers
$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$  since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.  
As a result subtraction can be performed with a trivial series of logical operations and an addition.

However, in multiple precision arithmetic negative numbers are not represented in the same way.  Instead a sign flag is used to keep track of the
sign of the integer.  As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or 
subtraction algorithms with the sign fixed up appropriately.

The lower level algorithms will add or subtract integers without regard to the sign flag.  That is they will add or subtract the magnitude of
the integers respectively.

\subsection{Low Level Addition}
An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers.  That is to add the 
trailing digits first and propagate the resulting carry upwards.  Since this is a lower level algorithm the name will have a ``s\_'' prefix.  
Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.

\newpage
\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
\hline \\
1.  if $a.used > b.used$ then \\
\hspace{+3mm}1.1  $min \leftarrow b.used$ \\
\hspace{+3mm}1.2  $max \leftarrow a.used$ \\
\hspace{+3mm}1.3  $x   \leftarrow a$ \\
2.  else  \\
\hspace{+3mm}2.1  $min \leftarrow a.used$ \\
\hspace{+3mm}2.2  $max \leftarrow b.used$ \\
\hspace{+3mm}2.3  $x   \leftarrow b$ \\
3.  If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\
5.  $c.used \leftarrow max + 1$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{+3mm}7.1  $c_n \leftarrow a_n + b_n + u$ \\
\hspace{+3mm}7.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min \ne max$ then do \\
\hspace{+3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{+6mm}8.1.1  $c_n \leftarrow x_n + u$ \\
\hspace{+6mm}8.1.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9.  $c_{max} \leftarrow u$ \\
10.  if $olduse > max$ then \\
\hspace{+3mm}10.1  for $n$ from $max + 1$ to $oldused - 1$ do \\
\hspace{+6mm}10.1.1  $c_n \leftarrow 0$ \\
11.  Clamp excess digits in $c$.  (\textit{mp\_clamp}) \\
12.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_add}
\end{figure}

\textbf{Algorithm s\_mp\_add.}
This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.  
Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}.  Even the 
MIX pseudo  machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.

The first thing that has to be accomplished is to sort out which of the two inputs is the largest.  The addition logic
will simply add all of the smallest input to the largest input and store that first part of the result in the
destination.  Then it will apply a simpler addition loop to excess digits of the larger input.

The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two 
inputs.  The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
same number of digits.  After the inputs are sorted the destination $c$ is grown as required to accomodate the sum 
of the two inputs.  The original \textbf{used} count of $c$ is copied and set to the new used count.  

At this point the first addition loop will go through as many digit positions that both inputs have.  The carry
variable $\mu$ is set to zero outside the loop.  Inside the loop an ``addition'' step requires three statements to produce
one digit of the summand.  First
two digits from $a$ and $b$ are added together along with the carry $\mu$.  The carry of this step is extracted and stored
in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.

Now all of the digit positions that both inputs have in common have been exhausted.  If $min \ne max$ then $x$ is an alias
for one of the inputs that has more digits.  A simplified addition loop is then used to essentially copy the remaining digits
and the carry to the destination.

The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.


EXAM,bn_s_mp_add.c

We first sort (lines @27,if@ to @35,}@) the inputs based on magnitude and determine the $min$ and $max$ variables.
Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias.  Next we
grow the destination (@37,init@ to @42,}@) ensure that it can accomodate the result of the addition. 

Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style.  The three aliases that are on 
lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively.  These aliases are used to ensure the
compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.

The initial carry $u$ will be cleared (line @65,u = 0@), note that $u$ is of type mp\_digit which ensures type 
compatibility within the implementation.  The initial addition (line @66,for@ to @75,}@) adds digits from
both inputs until the smallest input runs out of digits.  Similarly the conditional addition loop
(line @81,for@ to @90,}@) adds the remaining digits from the larger of the two inputs.  The addition is finished 
with the final carry being stored in $tmpc$ (line @94,tmpc++@).  Note the ``++'' operator within the same expression.
After line @94,tmpc++@, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$.  This is useful
for the next loop (line @97,for@ to @99,}@) which set any old upper digits to zero.

\subsection{Low Level Subtraction}
The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm.  The principle difference is that the
unsigned subtraction algorithm requires the result to be positive.  That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must 
be met for this algorithm to function properly.  Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.  
This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.

MARK,GAMMA

For this algorithm a new variable is required to make the description simpler.  Recall from section 1.3.1 that a mp\_digit must be able to represent
the range $0 \le x < 2\beta$ for the algorithms to work correctly.  However, it is allowable that a mp\_digit represent a larger range of values.  For 
this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a 
mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).  

For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$.  In ISO C an ``unsigned long''
data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.

\newpage\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
\textbf{Output}.  The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
\hline \\
1.  $min \leftarrow b.used$ \\
2.  $max \leftarrow a.used$ \\
3.  If $c.alloc < max$ then grow $c$ to hold at least $max$ digits.  (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\ 
5.  $c.used \leftarrow max$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{3mm}7.1  $c_n \leftarrow a_n - b_n - u$ \\
\hspace{3mm}7.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min < max$ then do \\
\hspace{3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{6mm}8.1.1  $c_n \leftarrow a_n - u$ \\
\hspace{6mm}8.1.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9. if $oldused > max$ then do \\
\hspace{3mm}9.1  for $n$ from $max$ to $oldused - 1$ do \\
\hspace{6mm}9.1.1  $c_n \leftarrow 0$ \\
10. Clamp excess digits of $c$.  (\textit{mp\_clamp}). \\
11. Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_sub}
\end{figure}

\textbf{Algorithm s\_mp\_sub.}
This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive.  That is when
passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly.  This
algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well.  As was the case
of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.

The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$.  Steps 1 and 2 
set the $min$ and $max$ variables.  Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at 
most $max$ digits in length as opposed to $max + 1$.  Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and 
set to the maximal count for the operation.

The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision 
subtraction is used instead.  Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction 
loops.  Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.  

For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$.  The least significant bit will force a carry upwards to 
the third bit which will be set to zero after the borrow.  After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain,  When the 
third bit of $0101_2$ is subtracted from the result it will cause another carry.  In this case though the carry will be forced to propagate all the 
way to the most significant bit.  

Recall that $\beta < 2^{\gamma}$.  This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most 
significant bit.  Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
is needed is a single zero or one bit for the carry.  Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the 
carry.  This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.  

If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$.  Step
10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.

EXAM,bn_s_mp_sub.c

Like low level addition we ``sort'' the inputs.  Except in this case the sorting is hardcoded 
(lines @24,min@ and @25,max@).  In reality the $min$ and $max$ variables are only aliases and are only 
used to make the source code easier to read.  Again the pointer alias optimization is used 
within this algorithm.  The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
(lines @42,tmpa@, @43,tmpb@ and @44,tmpc@) for $a$, $b$ and $c$ respectively.

The first subtraction loop (lines @47,u = 0@ through @61,}@) subtract digits from both inputs until the smaller of
the two inputs has been exhausted.  As remarked earlier there is an implementation reason for using the ``awkward'' 
method of extracting the carry (line @57, >>@).  The traditional method for extracting the carry would be to shift 
by $lg(\beta)$ positions and logically AND the least significant bit.  The AND operation is required because all of 
the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction.  This carry 
extraction requires two relatively cheap operations to extract the carry.  The other method is to simply shift the 
most significant bit to the least significant bit thus extracting the carry with a single cheap operation.  This 
optimization only works on twos compliment machines which is a safe assumption to make.

If $a$ has a larger magnitude than $b$ an additional loop (lines @64,for@ through @73,}@) is required to propagate 
the carry through $a$ and copy the result to $c$.  

\subsection{High Level Addition}
Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
established.  This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data 
types.  

Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} 
flag.  A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed addition $c = a + b$. \\
\hline \\
1.  if $a.sign = b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$  \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag})  \\
\hspace{6mm}2.1.1  $c.sign \leftarrow b.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert a \vert - \vert b \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_add}
\end{figure}

\textbf{Algorithm mp\_add.}
This algorithm performs the signed addition of two mp\_int variables.  There is no reference algorithm to draw upon from 
either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations.  The algorithm is fairly 
straightforward but restricted since subtraction can only produce positive results.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&&\\

\hline $+$ & $-$ & No  & $c = b - a$ & $b.sign$ \\
\hline $-$ & $+$ & No  & $c = b - a$ & $b.sign$ \\

\hline &&&&\\

\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\

\hline
\end{tabular}
\end{center}
\end{small}
\caption{Addition Guide Chart}
\label{fig:AddChart}
\end{figure}

Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three 
specific cases need to be handled.  The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are 
forwarded to step three to check for errors.  This simplifies the description of the algorithm considerably and best 
follows how the implementation actually was achieved.

Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed.  Recall from the descriptions of algorithms
s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits.  The mp\_clamp algorithm will set the \textbf{sign}
to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.

For example, consider performing $-a + a$ with algorithm mp\_add.  By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
produce a result of $-0$.  However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp 
within algorithm s\_mp\_add will force $-0$ to become $0$.  

EXAM,bn_mp_add.c

The source code follows the algorithm fairly closely.  The most notable new source code addition is the usage of the $res$ integer variable which
is used to pass result of the unsigned operations forward.  Unlike in the algorithm, the variable $res$ is merely returned as is without
explicitly checking it and returning the constant \textbf{MP\_OKAY}.  The observation is this algorithm will succeed or fail only if the lower
level functions do so.  Returning their return code is sufficient.

\subsection{High Level Subtraction}
The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.  

\newpage\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed subtraction $c = a - b$. \\
\hline \\
1.  if $a.sign \ne b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$ \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
\hspace{6mm}2.1.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert a \vert  - \vert b \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = MP\_NEG \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert b \vert  - \vert a \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_sub}
\end{figure}

\textbf{Algorithm mp\_sub.}
This algorithm performs the signed subtraction of two inputs.  Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or 
\cite{HAC}.  Also this algorithm is restricted by algorithm s\_mp\_sub.  Chart \ref{fig:SubChart} lists the eight possible inputs and
the operations required.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline $-$ & $-$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Subtraction Guide Chart}
\label{fig:SubChart}
\end{figure}

Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction.  That is to prevent the 
algorithm from producing $-a - -a = -0$ as a result.  

EXAM,bn_mp_sub.c

Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
and forward it to the end of the function.  On line @38, != MP_LT@ the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a 
``greater than or equal to'' comparison.  

\section{Bit and Digit Shifting}
MARK,POLY
It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.  
This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.  

In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established.  That is to shift
the digits left or right as well to shift individual bits of the digits left and right.  It is important to note that not all ``shift'' operations
are on radix-$\beta$ digits.  

\subsection{Multiplication by Two}

In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient 
operation to perform.  A single precision logical shift left is sufficient to multiply a single digit by two.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = 2a$. \\
\hline \\
1.  If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits.  (\textit{mp\_grow}) \\
2.  $oldused \leftarrow b.used$ \\
3.  $b.used \leftarrow a.used$ \\
4.  $r \leftarrow 0$ \\
5.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}5.1  $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
\hspace{3mm}5.2  $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.3  $r \leftarrow rr$ \\
6.  If $r \ne 0$ then do \\
\hspace{3mm}6.1  $b_{n + 1} \leftarrow r$ \\
\hspace{3mm}6.2  $b.used \leftarrow b.used + 1$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2}
\end{figure}

\textbf{Algorithm mp\_mul\_2.}
This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two.  Neither \cite{TAOCPV2} nor \cite{HAC} describe such 
an algorithm despite the fact it arises often in other algorithms.  The algorithm is setup much like the lower level algorithm s\_mp\_add since 
it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.  

Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result.  The initial \textbf{used} count
is set to $a.used$ at step 4.  Only if there is a final carry will the \textbf{used} count require adjustment.

Step 6 is an optimization implementation of the addition loop for this specific case.  That is since the two values being added together 
are the same there is no need to perform two reads from the digits of $a$.  Step 6.1 performs a single precision shift on the current digit $a_n$ to
obtain what will be the carry for the next iteration.  Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
the previous carry.  Recall from ~SHIFTS~ that $a_n << 1$ is equivalent to $a_n \cdot 2$.  An iteration of the addition loop is finished with 
forwarding the carry to the next iteration.

Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.  
Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.

EXAM,bn_mp_mul_2.c

This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input.  The only noteworthy difference
is the use of the logical shift operator on line @52,<<@ to perform a single precision doubling.  

\subsection{Division by Two}
A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = a/2$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits.  (\textit{mp\_grow}) \\
2.  If the reallocation failed return(\textit{MP\_MEM}). \\
3.  $oldused \leftarrow b.used$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $r \leftarrow 0$ \\
6.  for $n$ from $b.used - 1$ to $0$ do \\
\hspace{3mm}6.1  $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
\hspace{3mm}6.2  $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}6.3  $r \leftarrow rr$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Clamp excess digits of $b$.  (\textit{mp\_clamp}) \\
10.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2}
\end{figure}

\textbf{Algorithm mp\_div\_2.}
This algorithm will divide an mp\_int by two using logical shifts to the right.  Like mp\_mul\_2 it uses a modified low level addition
core as the basis of the algorithm.  Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit.  The algorithm
could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
reading past the end of the array of digits.

Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the 
least significant bit not the most significant bit.  

EXAM,bn_mp_div_2.c

\section{Polynomial Basis Operations}
Recall from ~POLY~ that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$.  Such a representation is also known as
the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single 
place.  The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
division and Karatsuba multiplication.  

Converting from an array of digits to polynomial basis is very simple.  Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
$y = \sum_{i=0}^{2} a_i \beta^i$.  Simply replace $\beta$ with $x$ and the expression is in polynomial basis.  For example, $f(x) = 8x + 9$ is the
polynomial basis representation for $89$ using radix ten.  That is, $f(10) = 8(10) + 9 = 89$.  

\subsection{Multiplication by $x$}

Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one 
degree.  In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$.  From a scalar basis point of view multiplying by $x$ is equivalent to
multiplying by the integer $\beta$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_OKAY}). \\
2.  If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits.  (\textit{mp\_grow}). \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  $a.used \leftarrow a.used + b$ \\
5.  $i \leftarrow a.used - 1$ \\
6.  $j \leftarrow a.used - 1 - b$ \\
7.  for $n$ from $a.used - 1$ to $b$ do \\
\hspace{3mm}7.1  $a_{i} \leftarrow a_{j}$ \\
\hspace{3mm}7.2  $i \leftarrow i - 1$ \\
\hspace{3mm}7.3  $j \leftarrow j - 1$ \\
8.  for $n$ from 0 to $b - 1$ do \\
\hspace{3mm}8.1  $a_n \leftarrow 0$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lshd}
\end{figure}

\textbf{Algorithm mp\_lshd.}
This algorithm multiplies an mp\_int by the $b$'th power of $x$.  This is equivalent to multiplying by $\beta^b$.  The algorithm differs 
from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location.  The
motivation behind this change is due to the way this function is typically used.  Algorithms such as mp\_add store the result in an optionally
different third mp\_int because the original inputs are often still required.  Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
typically used on values where the original value is no longer required.  The algorithm will return success immediately if 
$b \le 0$ since the rest of algorithm is only valid when $b > 0$.  

First the destination $a$ is grown as required to accomodate the result.  The counters $i$ and $j$ are used to form a \textit{sliding window} over
the digits of $a$ of length $b$.  The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).  
The loop on step 7 copies the digit from the tail to the head.  In each iteration the window is moved down one digit.   The last loop on 
step 8 sets the lower $b$ digits to zero.

\newpage
FIGU,sliding_window,Sliding Window Movement

EXAM,bn_mp_lshd.c

The if statement (line @24,if@) ensures that the $b$ variable is greater than zero since we do not interpret negative
shift counts properly.  The \textbf{used} count is incremented by $b$ before the copy loop begins.  This elminates 
the need for an additional variable in the for loop.  The variable $top$ (line @42,top@) is an alias
for the leading digit while $bottom$ (line @45,bottom@) is an alias for the trailing edge.  The aliases form a 
window of exactly $b$ digits over the input.  

\subsection{Division by $x$}

Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return. \\
2.  If $a.used \le b$ then do \\
\hspace{3mm}2.1  Zero $a$.  (\textit{mp\_zero}). \\
\hspace{3mm}2.2  Return. \\
3.  $i \leftarrow 0$ \\
4.  $j \leftarrow b$ \\
5.  for $n$ from 0 to $a.used - b - 1$ do \\
\hspace{3mm}5.1  $a_i \leftarrow a_j$ \\
\hspace{3mm}5.2  $i \leftarrow i + 1$ \\
\hspace{3mm}5.3  $j \leftarrow j + 1$ \\
6.  for $n$ from $a.used - b$ to $a.used - 1$ do \\
\hspace{3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.used \leftarrow a.used - b$ \\
8.  Return. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rshd}
\end{figure}

\textbf{Algorithm mp\_rshd.}
This algorithm divides the input in place by the $b$'th power of $x$.  It is analogous to dividing by a $\beta^b$ but much quicker since
it does not require single precision division.  This algorithm does not actually return an error code as it cannot fail.  

If the input $b$ is less than one the algorithm quickly returns without performing any work.  If the \textbf{used} count is less than or equal
to the shift count $b$ then it will simply zero the input and return.

After the trivial cases of inputs have been handled the sliding window is setup.  Much like the case of algorithm mp\_lshd a sliding window that
is $b$ digits wide is used to copy the digits.  Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.  
Also the digits are copied from the leading to the trailing edge.

Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.

EXAM,bn_mp_rshd.c

The only noteworthy element of this routine is the lack of a return type since it cannot fail.  Like mp\_lshd() we
form a sliding window except we copy in the other direction.  After the window (line @59,for (;@) we then zero
the upper digits of the input to make sure the result is correct.

\section{Powers of Two}

Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required.  For 
example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful.  Instead of performing single
shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.  

\subsection{Multiplication by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot 2^b$. \\
\hline \\
1.  $c \leftarrow a$.  (\textit{mp\_copy}) \\
2.  If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  If $b \ge lg(\beta)$ then \\
\hspace{3mm}4.1  $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
\hspace{3mm}4.2  If step 4.1 failed return(\textit{MP\_MEM}). \\
5.  $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $d \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^d$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $0$ to $c.used - 1$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
\hspace{3mm}6.4  If $r > 0$ then do \\
\hspace{6mm}6.4.1  $c_{c.used} \leftarrow r$ \\
\hspace{6mm}6.4.2  $c.used \leftarrow c.used + 1$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2d}
\end{figure}

\textbf{Algorithm mp\_mul\_2d.}
This algorithm multiplies $a$ by $2^b$ and stores the result in $c$.  The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
quickly compute the product.

First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than 
$\beta$.  For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ 
left.

After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform.  Step 5 calculates the number of remaining shifts 
required.  If it is non-zero a modified shift loop is used to calculate the remaining product.  
Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$.  The $mask$
variable is used to extract the upper $d$ bits to form the carry for the next iteration.  

This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to 
complete.  It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.

EXAM,bn_mp_mul_2d.c

The shifting is performed in--place which means the first step (line @24,a != c@) is to copy the input to the 
destination.  We avoid calling mp\_copy() by making sure the mp\_ints are different.  The destination then
has to be grown (line @31,grow@) to accomodate the result.

If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples 
of $lg(\beta)$.  Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left.  Inside the actual shift 
loop (lines @45,if@ to @76,}@) we make use of pre--computed values $shift$ and $mask$.   These are used to
extract the carry bit(s) to pass into the next iteration of the loop.  The $r$ and $rr$ variables form a 
chain between consecutive iterations to propagate the carry.  

\subsection{Division by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}1.2  $d \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.3  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow a$ \\
3.  $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
4.  If $b \ge lg(\beta)$ then do \\
\hspace{3mm}4.1  $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
5.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $k \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^k$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $c.used - 1$ to $0$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
7.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2d}
\end{figure}

\textbf{Algorithm mp\_div\_2d.}
This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder.  The algorithm is designed much like algorithm 
mp\_mul\_2d by first using whole digit shifts then single precision shifts.  This algorithm will also produce the remainder of the division
by using algorithm mp\_mod\_2d.

EXAM,bn_mp_div_2d.c

The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies.  The remainder $d$ may be optionally 
ignored by passing \textbf{NULL} as the pointer to the mp\_int variable.    The temporary mp\_int variable $t$ is used to hold the 
result of the remainder operation until the end.  This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
the quotient is obtained.

The remainder of the source code is essentially the same as the source code for mp\_mul\_2d.  The only significant difference is
the direction of the shifts.

\subsection{Remainder of Division by Power of Two}

The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$.  This
algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mod\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $b > a.used \cdot lg(\beta)$ then do \\
\hspace{3mm}2.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}2.2  Return the result of step 2.1. \\
3.  $c \leftarrow a$ \\
4.  If step 3 failed return(\textit{MP\_MEM}). \\
5.  for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
\hspace{3mm}5.1  $c_n \leftarrow 0$ \\
6.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
7.  $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
8.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mod\_2d}
\end{figure}

\textbf{Algorithm mp\_mod\_2d.}
This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$.  First if $b$ is less than or equal to zero the 
result is set to zero.  If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns.  Otherwise, $a$ 
is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.

EXAM,bn_mp_mod_2d.c

We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases.  Next if $2^b$ is larger
than the input we just mp\_copy() the input and return right away.  After this point we know we must actually
perform some work to produce the remainder.

Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce 
the number.  First we zero any digits above the last digit in $2^b$ (line @41,for@).  Next we reduce the 
leading digit of both (line @45,&=@) and then mp\_clamp().

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
                      & in $O(n)$ time. \\
                      &\\
$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming  \\
                      & weight values such as $3$, $5$ and $9$.  Extend it to handle all values \\
                      & upto $64$ with a hamming weight less than three. \\
                      &\\
$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
                      & $2^k - 1$ as well. \\
                      &\\
$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
                      & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
                      & any $n$-bit input.  Note that the time of addition is ignored in the \\
                      & calculation.  \\
                      & \\
$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
                      & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$.  Again ignore \\
                      & the cost of addition. \\
                      & \\
$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
                      & for $n = 64 \ldots 1024$ in steps of $64$. \\
                      & \\
$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
                      & calculating the result of a signed comparison. \\
                      &
\end{tabular}

\chapter{Multiplication and Squaring}
\section{The Multipliers}
For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of 
algorithms of any multiple precision integer package.  The set of multiplier algorithms include integer multiplication, squaring and modular reduction 
where in each of the algorithms single precision multiplication is the dominant operation performed.  This chapter will discuss integer multiplication 
and squaring, leaving modular reductions for the subsequent chapter.  

The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular 
exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$.  During a modular
exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, 
35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision 
multiplications.

For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied 
against every digit of the other multiplicand.  Traditional long-hand multiplication is based on this process;  while the techniques can differ the 
overall algorithm used is essentially the same.  Only ``recently'' have faster algorithms been studied.  First Karatsuba multiplication was discovered in 
1962.  This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.  
This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.  

\section{Multiplication}
\subsection{The Baseline Multiplication}
\label{sec:basemult}
\index{baseline multiplication}
Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
algorithm that school children are taught.  The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision 
multiplications are required.  More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required.  To 
simplify most discussions, it will be assumed that the inputs have comparable number of digits.  

The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be 
used.  This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible.    One important 
facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution.  The importance of this 
modification will become evident during the discussion of Barrett modular reduction.  Recall that for a $n$ and $m$ digit input the product 
will be at most $n + m$ digits.  Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.  

Recall from ~GAMMA~ the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}.  We shall now extend the variable set to 
include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}.  This implies that $2^{\alpha} > 2 \cdot \beta^2$.  The 
constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see ~COMBA~ for more information}).

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
1.  If min$(a.used, b.used) < \delta$ then do \\
\hspace{3mm}1.1  Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}).  \\
\hspace{3mm}1.2  Return the result of step 1.1 \\
\\
Allocate and initialize a temporary mp\_int. \\
2.  Init $t$ to be of size $digs$ \\
3.  If step 2 failed return(\textit{MP\_MEM}). \\
4.  $t.used \leftarrow digs$ \\
\\
Compute the product. \\
5.  for $ix$ from $0$ to $a.used - 1$ do \\
\hspace{3mm}5.1  $u \leftarrow 0$ \\
\hspace{3mm}5.2  $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
\hspace{3mm}5.3  If $pb < 1$ then goto step 6. \\
\hspace{3mm}5.4  for $iy$ from $0$ to $pb - 1$ do \\
\hspace{6mm}5.4.1  $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
\hspace{6mm}5.4.2  $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.5  if $ix + pb < digs$ then do \\
\hspace{6mm}5.5.1  $t_{ix + pb} \leftarrow u$ \\
6.  Clamp excess digits of $t$. \\
7.  Swap $c$ with $t$ \\
8.  Clear $t$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_mul\_digs}
\end{figure}

\textbf{Algorithm s\_mp\_mul\_digs.}
This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits.  While it may seem
a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent 
algorithm.  The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.  
Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the 
inputs.

The first thing this algorithm checks for is whether a Comba multiplier can be used instead.   If the minimum digit count of either
input is less than $\delta$, then the Comba method may be used instead.    After the Comba method is ruled out, the baseline algorithm begins.  A 
temporary mp\_int variable $t$ is used to hold the intermediate result of the product.  This allows the algorithm to be used to 
compute products when either $a = c$ or $b = c$ without overwriting the inputs.  

All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output.  The $pb$ variable
is given the count of digits to read from $b$ inside the nested loop.  If $pb \le 1$ then no more output digits can be produced and the algorithm
will exit the loop.  The best way to think of the loops are as a series of $pb \times 1$ multiplications.    That is, in each pass of the 
innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.  

For example, consider multiplying $576$ by $241$.  That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
visualized in the following table.

\begin{figure}[here]
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|l|}
\hline   &&          & 5 & 7 & 6 & \\
\hline   $\times$&&  & 2 & 4 & 1 & \\
\hline &&&&&&\\
  &&          & 5 & 7 & 6 & $10^0(1)(576)$ \\
  &2 &   3    & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
  1 & 3 & 8 & 8 & 1 & 6 &   $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
\hline  
\end{tabular}
\end{center}
\caption{Long-Hand Multiplication Diagram}
\end{figure}

Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate 
count.  That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.

Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable.  The multiplication on that step
is assumed to be a double wide output single precision multiplication.  That is, two single precision variables are multiplied to produce a
double precision result.  The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
5.4.1 is propagated through the nested loop.  If the carry was not propagated immediately it would overflow the single precision digit 
$t_{ix+iy}$ and the result would be lost.  

At step 5.5 the nested loop is finished and any carry that was left over should be forwarded.  The carry does not have to be added to the $ix+pb$'th
digit since that digit is assumed to be zero at this point.  However, if $ix + pb \ge digs$ the carry is not set as it would make the result
exceed the precision requested.

EXAM,bn_s_mp_mul_digs.c

First we determine (line @30,if@) if the Comba method can be used first since it's faster.  The conditions for 
sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than 
\textbf{MP\_WARRAY}.  This new constant is used to control the stack usage in the Comba routines.  By default it is 
set to $\delta$ but can be reduced when memory is at a premium.

If we cannot use the Comba method we proceed to setup the baseline routine.  We allocate the the destination mp\_int
$t$ (line @36,init@) to the exact size of the output to avoid further re--allocations.  At this point we now 
begin the $O(n^2)$ loop.

This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
digits as output.  In each iteration of the outer loop the $pb$ variable is set (line @48,MIN@) to the maximum 
number of inner loop iterations.  

Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
carry from the previous iteration.  A particularly important observation is that most modern optimizing 
C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that 
is required for the product.  In x86 terms for example, this means using the MUL instruction.

Each digit of the product is stored in turn (line @68,tmpt@) and the carry propagated (line @71,>>@) to the 
next iteration.

\subsection{Faster Multiplication by the ``Comba'' Method}
MARK,COMBA

One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be 
computed and propagated upwards.  This makes the nested loop very sequential and hard to unroll and implement 
in parallel.  The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. 
Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations.  As an 
interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written 
five years before.

At the heart of the Comba technique is once again the long-hand algorithm.  Except in this case a slight 
twist is placed on how the columns of the result are produced.  In the standard long-hand algorithm rows of products 
are produced then added together to form the final result.  In the baseline algorithm the columns are added together 
after each iteration to get the result instantaneously.  

In the Comba algorithm the columns of the result are produced entirely independently of each other.  That is at 
the $O(n^2)$ level a simple multiplication and addition step is performed.  The carries of the columns are propagated 
after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute 
the product vector $\vec x$ as follows. 

\begin{equation}
\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
\end{equation}

Where $\vec x_n$ is the $n'th$ column of the output vector.  Consider the following example which computes the vector $\vec x$ for the multiplication
of $576$ and $241$.  

\newpage\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|}
  \hline &          & 5 & 7 & 6 & First Input\\
  \hline $\times$ & & 2 & 4 & 1 & Second Input\\
\hline            &                        & $1 \cdot 5 = 5$   & $1 \cdot 7 = 7$   & $1 \cdot 6 = 6$ & First pass \\
                  &  $4 \cdot 5 = 20$      & $4 \cdot 7+5=33$  & $4 \cdot 6+7=31$  & 6               & Second pass \\
   $2 \cdot 5 = 10$ &  $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31                & 6             & Third pass \\
\hline 10 & 34 & 45 & 31 & 6 & Final Result \\   
\hline   
\end{tabular}
\end{center}
\end{small}
\caption{Comba Multiplication Diagram}
\end{figure}

At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.  
Now the columns must be fixed by propagating the carry upwards.  The resultant vector will have one extra dimension over the input vector which is
congruent to adding a leading zero digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Comba Fixup}. \\
\textbf{Input}.   Vector $\vec x$ of dimension $k$ \\
\textbf{Output}.  Vector $\vec x$ such that the carries have been propagated. \\
\hline \\
1.  for $n$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
2.  Return($\vec x$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Comba Fixup}
\end{figure}

With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$.  In this case 
$241 \cdot 576$ is in fact $138816$ and the procedure succeeded.  If the algorithm is correct and as will be demonstrated shortly more
efficient than the baseline algorithm why not simply always use this algorithm?

\subsubsection{Column Weight.}
At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output 
independently.  A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
the carries.  For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
three single precision multiplications.  If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
an overflow can occur and the carry information will be lost.  For any $m$ and $n$ digit inputs the maximum weight of any column is 
min$(m, n)$ which is fairly obvious.

The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used.  Recall
from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision.  Given these
two quantities we must not violate the following

\begin{equation}
k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
\end{equation}

Which reduces to 

\begin{equation}
k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
\end{equation}

Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit.  By further re-arrangement of the equation the final solution is
found.

\begin{equation}
k  < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
\end{equation}

The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$.  In this configuration 
the smaller input may not have more than $256$ digits if the Comba method is to be used.  This is quite satisfactory for most applications since 
$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
1.  If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
2.  If step 1 failed return(\textit{MP\_MEM}).\\
\\
3.  $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
\\
4.  $\_ \hat W \leftarrow 0$ \\
5.  for $ix$ from 0 to $pa - 1$ do \\
\hspace{3mm}5.1  $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
\hspace{3mm}5.2  $tx \leftarrow ix - ty$ \\
\hspace{3mm}5.3  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
\hspace{3mm}5.4  for $iz$ from 0 to $iy - 1$ do \\
\hspace{6mm}5.4.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
\hspace{3mm}5.5  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
\hspace{3mm}5.6  $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
\\
6.  $oldused \leftarrow c.used$ \\
7.  $c.used \leftarrow digs$ \\
8.  for $ix$ from $0$ to $pa$ do \\
\hspace{3mm}8.1  $c_{ix} \leftarrow W_{ix}$ \\
9.  for $ix$ from $pa + 1$ to $oldused - 1$ do \\
\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
\\
10.  Clamp $c$. \\
11.  Return MP\_OKAY. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_mul\_digs}
\label{fig:COMBAMULT}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_mul\_digs.}
This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.

The outer loop of this algorithm is more complicated than that of the baseline multiplier.  This is because on the inside of the 
loop we want to produce one column per pass.  This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.

The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$.  That way if $a$ has more digits than
$b$ this will be limited to $b.used - 1$.  The $tx$ variable is set to the to the distance past $b.used$ the variable
$ix$ is.  This is used for the immediately subsequent statement where we find $iy$.  

The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out.  Computing one column at a time
means we have to scan one integer upwards and the other downwards.  $a$ starts at $tx$ and $b$ starts at $ty$.  In each
pass we are producing the $ix$'th output column and we note that $tx + ty = ix$.  As we move $tx$ upwards we have to 
move $ty$ downards so the equality remains valid.  The $iy$ variable is the number of iterations until 
$tx \ge a.used$ or $ty < 0$ occurs.

After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
into the next round by dividing $\_ \hat W$ by $\beta$.

To measure the benefits of the Comba method over the baseline method consider the number of operations that are required.  If the 
cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require 
$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers.  The Comba method requires only $O(pn^2 + qn)$ time, however in practice, 
the speed increase is actually much more.  With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
and addition operations in the nested loop in parallel.  

EXAM,bn_fast_s_mp_mul_digs.c

As per the pseudo--code we first calculate $pa$ (line @47,MIN@) as the number of digits to output.  Next we begin the outer loop
to produce the individual columns of the product.  We use the two aliases $tmpx$ and $tmpy$ (lines @61,tmpx@, @62,tmpy@) to point
inside the two multiplicands quickly.  

The inner loop (lines @70,for@ to @72,}@) of this implementation is where the tradeoff come into play.  Originally this comba 
implementation was ``row--major'' which means it adds to each of the columns in each pass.  After the outer loop it would then fix 
the carries.  This was very fast except it had an annoying drawback.  You had to read a mp\_word and two mp\_digits and write 
one mp\_word per iteration.  On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth 
is very high and it can keep the ALU fed with data.  It did, however, matter on older and embedded cpus where cache is often 
slower and also often doesn't exist.  This new algorithm only performs two reads per iteration under the assumption that the 
compiler has aliased $\_ \hat W$ to a CPU register.

After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines @75,W[ix]@, @78,>>@) to forward it as 
a carry for the next pass.  After the outer loop we use the final carry (line @82,W[ix]@) as the last digit of the product.  

\subsection{Polynomial Basis Multiplication}
To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication.  In the following algorithms
the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and  
$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required.  In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
 
The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$.  The coefficients $w_i$ will
directly yield the desired product when $\beta$ is substituted for $x$.  The direct solution to solve for the $2n + 1$ coefficients
requires $O(n^2)$ time and would in practice be slower than the Comba technique.

However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown 
coefficients.   This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with 
Gaussian elimination.  This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in 
effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.  

The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible.  However, since 
$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place.  The benefit of this technique stems from the 
fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively.  As a result finding the $2n + 1$ relations required 
by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.

When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$.  The $\zeta_0$ term
is simply the product $W(0) = w_0 = a_0 \cdot b_0$.  The $\zeta_1$ term is the product 
$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$.  The third point $\zeta_{\infty}$ is less obvious but rather
simple to explain.  The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.  
The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$.  Note that the 
points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.

If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ for small values of $q$.  The term ``mirror point'' stems from the fact that 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$.  For
example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.

\begin{eqnarray}
\zeta_{2}                  = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
\end{eqnarray}

Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts.  For example, when $n = 2$ the
polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$.  This technique of polynomial representation is known as Horner's method.  

As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications.  Each multiplication is of 
multiplicands that have $n$ times fewer digits than the inputs.  The asymptotic running time of this algorithm is 
$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}).  Figure~\ref{fig:exponent}
summarizes the exponents for various values of $n$.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Split into $n$ Parts} & \textbf{Exponent}  & \textbf{Notes}\\
\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
\hline $4$ & $1.403677461$ &\\
\hline $5$ & $1.365212389$ &\\
\hline $10$ & $1.278753601$ &\\
\hline $100$ & $1.149426538$ &\\
\hline $1000$ & $1.100270931$ &\\
\hline $10000$ & $1.075252070$ &\\
\hline
\end{tabular}
\end{center}
\caption{Asymptotic Running Time of Polynomial Basis Multiplication}
\label{fig:exponent}
\end{figure}

At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$.  However, the overhead
of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
numbers.  

\subsubsection{Cutoff Point}
The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach.  However, 
the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved.  This makes the
polynomial basis approach more costly to use with small inputs.

Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}).  There exists a 
point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and 
when $m > y$ the Comba methods are slower than the polynomial basis algorithms.  

The exact location of $y$ depends on several key architectural elements of the computer platform in question.

\begin{enumerate}
\item  The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc.  For example
on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$.  The higher the ratio in favour of multiplication the lower
the cutoff point $y$ will be.  

\item  The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is.  Generally speaking as the number of splits
grows the complexity grows substantially.  Ideally solving the system will only involve addition, subtraction and shifting of integers.  This
directly reflects on the ratio previous mentioned.

\item  To a lesser extent memory bandwidth and function call overheads.  Provided the values are in the processor cache this is less of an
influence over the cutoff point.

\end{enumerate}

A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met.  For example, if the point
is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster.  Finding the cutoff points is fairly simple when
a high resolution timer is available.  

\subsection{Karatsuba Multiplication}
Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
general purpose multiplication.  Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with 
light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.

\begin{equation}
f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd
\end{equation}

Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product.  Applying
this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique.  It turns 
out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points 
$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$.  Consider the resultant system of equations.

\begin{center}
\begin{tabular}{rcrcrcrc}
$\zeta_{0}$ &      $=$ &  &  &  & & $w_0$ \\
$\zeta_{1}$ &      $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\
$\zeta_{\infty}$ & $=$ & $w_2$ &  & &  & \\
\end{tabular}
\end{center}

By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for.  The simplicity
of this system of equations has made Karatsuba fairly popular.  In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
\hline \\
1.  Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
2.  If step 2 failed then return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1 \cdot \beta^B + x0$ \\
3.  $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
6.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
7.  $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
\\
Calculate the three products. \\
8.  $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
9.  $x1y1 \leftarrow x1 \cdot y1$ \\
10.  $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\
11.  $x0 \leftarrow y1 + y0$ \\
12.  $t1 \leftarrow t1 \cdot x0$ \\
\\
Calculate the middle term. \\
13.  $x0 \leftarrow x0y0 + x1y1$ \\
14.  $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\
\\
Calculate the final product. \\
15.  $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
16.  $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
17.  $t1 \leftarrow x0y0 + t1$ \\
18.  $c \leftarrow t1 + x1y1$ \\
19.  Clear all of the temporary variables. \\
20.  Return(\textit{MP\_OKAY}).\\
\hline 
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_mul}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_mul.}
This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm.  It is loosely based on the description
from Knuth \cite[pp. 294-295]{TAOCPV2}.  

\index{radix point}
In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen.  The radix point chosen must
be used for both of the inputs meaning that it must be smaller than the smallest input.  Step 3 chooses the radix point $B$ as half of the 
smallest input \textbf{used} count.  After the radix point is chosen the inputs are split into lower and upper halves.  Step 4 and 5 
compute the lower halves.  Step 6 and 7 computer the upper halves.  

After the halves have been computed the three intermediate half-size products must be computed.  Step 8 and 9 compute the trivial products
$x0 \cdot y0$ and $x1 \cdot y1$.  The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed.  By using $x0$ instead
of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.

The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.

EXAM,bn_mp_karatsuba_mul.c

The new coding element in this routine, not  seen in previous routines, is the usage of goto statements.  The conventional
wisdom is that goto statements should be avoided.  This is generally true, however when every single function call can fail, it makes sense
to handle error recovery with a single piece of code.  Lines @61,if@ to @75,if@ handle initializing all of the temporary variables 
required.  Note how each of the if statements goes to a different label in case of failure.  This allows the routine to correctly free only
the temporaries that have been successfully allocated so far.

The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large.  This saves the 
additional reallocation that would have been necessary.  Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
number of digits for the next section of code.

The first algebraic portion of the algorithm is to split the two inputs into their halves.  However, instead of using mp\_mod\_2d and mp\_rshd
to extract the halves, the respective code has been placed inline within the body of the function.  To initialize the halves, the \textbf{used} and 
\textbf{sign} members are copied first.  The first for loop on line @98,for@ copies the lower halves.  Since they are both the same magnitude it 
is simpler to calculate both lower halves in a single loop.  The for loop on lines @104,for@ and @109,for@ calculate the upper halves $x1$ and 
$y1$ respectively.

By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.

When line @152,err@ is reached, the algorithm has completed succesfully.  The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
the same code that handles errors can be used to clear the temporary variables and return.  

\subsection{Toom-Cook $3$-Way Multiplication}
Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points  are 
chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce.  Here, the points $\zeta_{0}$, 
$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients 
of the $W(x)$.

With the five relations that Toom-Cook specifies, the following system of equations is formed.

\begin{center}
\begin{tabular}{rcrcrcrcrcr}
$\zeta_0$                    & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$  \\
$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$  \\
$\zeta_1$                    & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$  \\
$\zeta_2$                    & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$  \\
$\zeta_{\infty}$             & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$  \\
\end{tabular}
\end{center}

A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
of two, two divisions by three and one multiplication by three.  All of these $19$ sub-operations require less than quadratic time, meaning that
the algorithm can be faster than a baseline multiplication.  However, the greater complexity of this algorithm places the cutoff point
(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow  a  \cdot  b $ \\
\hline \\
Split $a$ and $b$ into three pieces.  E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
1.  $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
2.  $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
3.  $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
4.  $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
5.  $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
6.  $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
7.  $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
\\
Find the five equations for $w_0, w_1, ..., w_4$. \\
8.  $w_0 \leftarrow a_0 \cdot b_0$ \\
9.  $w_4 \leftarrow a_2 \cdot b_2$ \\
10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
\\
Continued on the next page.\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot  b $ \\
\hline \\
Now solve the system of equations. \\
18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
\\
Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
26. for $n$ from $1$ to $4$ do \\
\hspace{3mm}26.1  $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
28. Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul (continued)}
\end{figure}

\textbf{Algorithm mp\_toom\_mul.}
This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach.  Compared to the Karatsuba multiplication, this 
algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead.  In this
description, several statements have been compounded to save space.  The intention is that the statements are executed from left to right across
any given step.

The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively.  From these smaller
integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.

The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively.  The relation $w_1, w_2$ and $w_3$ correspond
to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively.  These are found using logical shifts to independently find
$f(y)$ and $g(y)$ which significantly speeds up the algorithm.

After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients 
$w_1, w_2$ and $w_3$ to be isolated.  The steps 18 through 25 perform the system reduction required as previously described.  Each step of
the reduction represents the comparable matrix operation that would be performed had this been performed by pencil.  For example, step 18 indicates
that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.  

Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known.  By substituting $\beta^{k}$ for $x$, the integer 
result $a \cdot b$ is produced.

EXAM,bn_mp_toom_mul.c

The first obvious thing to note is that this algorithm is complicated.  The complexity is worth it if you are multiplying very 
large numbers.  For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$).  For most ``crypto'' sized numbers this
algorithm is not practical as Karatsuba has a much lower cutoff point.

First we split $a$ and $b$ into three roughly equal portions.  This has been accomplished (lines @40,mod@ to @69,rshd@) with 
combinations of mp\_rshd() and mp\_mod\_2d() function calls.  At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
for $b$.  

Next we compute the five points $w0, w1, w2, w3$ and $w4$.  Recall that $w0$ and $w4$ can be computed directly from the portions so
we get those out of the way first (lines @72,mul@ and @77,mul@).  Next we compute $w1, w2$ and $w3$ using Horners method.

After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
straight forward.  

\subsection{Signed Multiplication}
Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required.  So far all
of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot b$ \\
\hline \\
1.  If $a.sign = b.sign$ then \\
\hspace{3mm}1.1  $sign = MP\_ZPOS$ \\
2.  else \\
\hspace{3mm}2.1  $sign = MP\_ZNEG$ \\
3.  If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then  \\
\hspace{3mm}3.1  $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
4.  else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
\hspace{3mm}4.1  $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
5.  else \\
\hspace{3mm}5.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}5.2  If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
\hspace{6mm}5.2.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs.  \\
\hspace{3mm}5.3  else \\
\hspace{6mm}5.3.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs.  \\
6.  $c.sign \leftarrow sign$ \\
7.  Return the result of the unsigned multiplication performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul}
\end{figure}

\textbf{Algorithm mp\_mul.}
This algorithm performs the signed multiplication of two inputs.  It will make use of any of the three unsigned multiplication algorithms 
available when the input is of appropriate size.  The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
s\_mp\_mul\_digs will clear it.  

EXAM,bn_mp_mul.c

The implementation is rather simplistic and is not particularly noteworthy.  Line @22,?@ computes the sign of the result using the ``?'' 
operator from the C programming language.  Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.  

\section{Squaring}
\label{sec:basesquare}

Squaring is a special case of multiplication where both multiplicands are equal.  At first it may seem like there is no significant optimization
available but in fact there is.  Consider the multiplication of $576$ against $241$.  In total there will be nine single precision multiplications
performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot  6$, $2 \cdot 7$ and $2 \cdot 5$.  Now consider 
the multiplication of $123$ against $123$.  The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, 
$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$.  On closer inspection some of the products are equivalent.  For example, $3 \cdot 2 = 2 \cdot 3$ 
and $3 \cdot 1 = 1 \cdot 3$. 

For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
required for multiplication.  The following diagram gives an example of the operations required.

\begin{figure}[here]
\begin{center}
\begin{tabular}{ccccc|c}
&&1&2&3&\\
$\times$ &&1&2&3&\\
\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
       & $2 \cdot 1$  & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
         $1 \cdot 1$  & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
\end{tabular}
\end{center}
\caption{Squaring Optimization Diagram}
\end{figure}

MARK,SQUARE
Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious.  For the purposes of this discussion let $x$
represent the number being squared.  The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.  

The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product.  Every non-square term of a column will
appear twice hence the name ``double product''.  Every odd column is made up entirely of double products.  In fact every column is made up of double 
products and at most one square (\textit{see the exercise section}).  

The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, 
occurs at column $2k + 1$.  For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. 
Column two of row one is a square and column three is the first unique column.

\subsection{The Baseline Squaring Algorithm}
The baseline squaring algorithm is meant to be a catch-all squaring algorithm.  It will handle any of the input sizes that the faster routines
will not handle.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits.  (\textit{mp\_init\_size}) \\
2.  If step 1 failed return(\textit{MP\_MEM}) \\
3.  $t.used \leftarrow 2 \cdot a.used + 1$ \\
4.  For $ix$ from 0 to $a.used - 1$ do \\
\hspace{3mm}Calculate the square. \\
\hspace{3mm}4.1  $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
\hspace{3mm}4.2  $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}Calculate the double products after the square. \\
\hspace{3mm}4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}4.4  For $iy$ from $ix + 1$ to $a.used - 1$ do \\
\hspace{6mm}4.4.1  $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
\hspace{6mm}4.4.2  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}Set the last carry. \\
\hspace{3mm}4.5  While $u > 0$ do \\
\hspace{6mm}4.5.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}4.5.2  $\hat r \leftarrow t_{ix + iy} + u$ \\
\hspace{6mm}4.5.3  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.5.4  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  Clamp excess digits of $t$.  (\textit{mp\_clamp}) \\
6.  Exchange $b$ and $t$. \\
7.  Clear $t$ (\textit{mp\_clear}) \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_sqr}
\end{figure}

\textbf{Algorithm s\_mp\_sqr.}
This algorithm computes the square of an input using the three observations on squaring.  It is based fairly faithfully on  algorithm 14.16 of HAC
\cite[pp.596-597]{HAC}.  Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring.  This allows the 
destination mp\_int to be the same as the source mp\_int.

The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
the inner loop computes the columns of the partial result.  Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
the carry and compute the double products.  

The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
very algorithm.  The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
when it is multiplied by two, it can be properly represented by a mp\_word.

Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial 
results calculated so far.  This involves expensive carry propagation which will be eliminated in the next algorithm.  

EXAM,bn_s_mp_sqr.c

Inside the outer loop (line @32,for@) the square term is calculated on line @35,r =@.  The carry (line @42,>>@) has been
extracted from the mp\_word accumulator using a right shift.  Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized 
(lines @45,tmpx@ and @48,tmpt@) to simplify the inner loop.  The doubling is performed using two
additions (line @57,r + r@) since it is usually faster than shifting, if not at least as fast.  

The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication.  As such the inner loops
get progressively shorter as the algorithm proceeds.  This is what leads to the savings compared to using a multiplication to
square a number. 

\subsection{Faster Squaring by the ``Comba'' Method}
A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop.  Squaring has an additional
drawback that it must double the product inside the inner loop as well.  As for multiplication, the Comba technique can be used to eliminate these
performance hazards.

The first obvious solution is to make an array of mp\_words which will hold all of the columns.  This will indeed eliminate all of the carry
propagation operations from the inner loop.  However, the inner product must still be doubled $O(n^2)$ times.  The solution stems from the simple fact
that $2a + 2b + 2c = 2(a + b + c)$.  That is the sum of all of the double products is equal to double the sum of all the products.  For example,
$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.  

However, we cannot simply double all of the columns, since the squares appear only once per row.  The most practical solution is to have two 
mp\_word arrays.  One array will hold the squares and the other array will hold the double products.  With both arrays the doubling and 
carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level.  In this case, we have an even simpler solution in mind.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
1.  If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits.  (\textit{mp\_grow}). \\
2.  If step 1 failed return(\textit{MP\_MEM}). \\
\\
3.  $pa \leftarrow 2 \cdot a.used$ \\
4.  $\hat W1 \leftarrow 0$ \\
5.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}5.1  $\_ \hat W \leftarrow 0$ \\
\hspace{3mm}5.2  $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
\hspace{3mm}5.3  $tx \leftarrow ix - ty$ \\
\hspace{3mm}5.4  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
\hspace{3mm}5.5  $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
\hspace{3mm}5.6  for $iz$ from $0$ to $iz - 1$ do \\
\hspace{6mm}5.6.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
\hspace{3mm}5.7  $\_ \hat W \leftarrow 2 \cdot \_ \hat W  + \hat W1$ \\
\hspace{3mm}5.8  if $ix$ is even then \\
\hspace{6mm}5.8.1  $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
\hspace{3mm}5.9  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
\hspace{3mm}5.10  $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
\\
6.  $oldused \leftarrow b.used$ \\
7.  $b.used \leftarrow 2 \cdot a.used$ \\
8.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}8.1  $b_{ix} \leftarrow W_{ix}$ \\
9.  for $ix$ from $pa$ to $oldused - 1$ do \\
\hspace{3mm}9.1  $b_{ix} \leftarrow 0$ \\
10.  Clamp excess digits from $b$.  (\textit{mp\_clamp}) \\
11.  Return(\textit{MP\_OKAY}). \\ 
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_sqr}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_sqr.}
This algorithm computes the square of an input using the Comba technique.  It is designed to be a replacement for algorithm 
s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.  
This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.

First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively.  This is because the inner loop
products are to be doubled.  If we had added the previous carry in we would be doubling too much.  Next we perform an
addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits.  For example, $a_3 \cdot a_5$ is equal
$a_5 \cdot a_3$.  Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum
of the products just outside the inner loop we have to avoid doing this.  This is also a good thing since we perform
fewer multiplications and the routine ends up being faster.

Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8).  We add in the square
only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.

EXAM,bn_fast_s_mp_sqr.c

This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for 
the special case of squaring.  

\subsection{Polynomial Basis Squaring}
The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring.  The minor exception
is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$.  Instead of performing $2n + 1$
multiplications to find the $\zeta$ relations, squaring operations are performed instead.  

\subsection{Karatsuba Squaring}
Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.  
Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial.  The Karatsuba equation can be modified to square a 
number with the following equation.

\begin{equation}
h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2
\end{equation}

Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$.  As in 
Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of 
$O \left ( n^{lg(3)} \right )$.

If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm 
instead?  The answer to this arises from the cutoff point for squaring.  As in multiplication there exists a cutoff point, at which the 
time required for a Comba based squaring and a Karatsuba based squaring meet.  Due to the overhead inherent in the Karatsuba method, the cutoff 
point is fairly high.  For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.  

Consider squaring a 200 digit number with this technique.  It will be split into two 100 digit halves which are subsequently squared.  
The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm.  If Karatsuba multiplication
were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Initialize the following temporary mp\_ints:  $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
2.  If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1\beta^B + x0$ \\
3.  $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
\\
Calculate the three squares. \\
6.  $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
7.  $x1x1 \leftarrow x1^2$ \\
8.  $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\
9.  $t1 \leftarrow t1^2$ \\
\\
Compute the middle term. \\
10.  $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
11.  $t1 \leftarrow t1 - t2$ \\
\\
Compute final product. \\
12.  $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
13.  $x1x1 \leftarrow x1x1\beta^{2B}$ \\
14.  $t1 \leftarrow t1 + x0x0$ \\
15.  $b \leftarrow t1 + x1x1$ \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_sqr}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_sqr.}
This algorithm computes the square of an input $a$ using the Karatsuba technique.  This algorithm is very similar to the Karatsuba based
multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.

The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
placed just below the middle.  Step 3, 4 and 5 compute the two halves required using $B$
as the radix point.  The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.

By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2)  = 2 \cdot x0 \cdot x1$.
Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
this method is faster.  Assuming no further recursions occur, the difference can be estimated with the following inequality.

Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
machine clock cycles.}. 

\begin{equation}
5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
\end{equation}

For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$.  This implies that the following inequality should hold.
\begin{center}
\begin{tabular}{rcl}
${5n \over 3} + 3n^2 + 3n$     & $<$ & ${n \over 3} + 6n^2$ \\
${5 \over 3} + 3n + 3$     & $<$ & ${1 \over 3} + 6n$ \\
${13 \over 9}$     & $<$ & $n$ \\
\end{tabular}
\end{center}

This results in a cutoff point around $n = 2$.  As a consequence it is actually faster to compute the middle term the ``long way'' on processors
where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication.  On
the Intel P4 processor this ratio is 1:29 making this method even more beneficial.  The only common exception is the ARMv4 processor which has a
ratio of 1:7.  } than simpler operations such as addition.  

EXAM,bn_mp_karatsuba_sqr.c

This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul.  It uses the same inline style to copy and 
shift the input into the two halves.  The loop from line @54,{@ to line @70,}@ has been modified since only one input exists.  The \textbf{used}
count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin.  At this point $x1$ and $x0$ are valid equivalents
to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.  

By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered.  On the Athlon the cutoff point
is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}).  On slower processors such as the Intel P4
it is actually below the Comba limit (\textit{at 110 digits}).

This routine uses the same error trap coding style as mp\_karatsuba\_sqr.  As the temporary variables are initialized errors are 
redirected to the error trap higher up.  If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and 
mp\_clears are executed normally.

\subsection{Toom-Cook Squaring}
The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
instead of multiplication to find the five relations.  The reader is encouraged to read the description of the latter algorithm and try to 
derive their own Toom-Cook squaring algorithm.  

\subsection{High Level Squaring}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  If $a.used \ge TOOM\_SQR\_CUTOFF$ then  \\
\hspace{3mm}1.1  $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
2.  else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
\hspace{3mm}2.1  $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
3.  else \\
\hspace{3mm}3.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}3.2  If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
\hspace{6mm}3.2.1  $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr.  \\
\hspace{3mm}3.3  else \\
\hspace{6mm}3.3.1  $b \leftarrow a^2$ using algorithm s\_mp\_sqr.  \\
4.  $b.sign \leftarrow MP\_ZPOS$ \\
5.  Return the result of the unsigned squaring performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_sqr}
\end{figure}

\textbf{Algorithm mp\_sqr.}
This algorithm computes the square of the input using one of four different algorithms.  If the input is very large and has at least
\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used.  If
neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.  

EXAM,bn_mp_sqr.c

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
                      & that have different number of digits in Karatsuba multiplication. \\
                      & \\
$\left [ 2 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\
                      & of double products and at most one square is stated.  Prove this statement. \\
                      & \\                      
$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
                      & \\
$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
                      & \\ 
$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
                      & required for equation $6.7$ to be true.  \\
                      & \\
$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
                      & compute subsets of the columns in each thread.  Determine a cutoff point where \\
                      & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
                      &\\
$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook.  You must \\
                      & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
                      & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
                      & \\
\end{tabular}

\chapter{Modular Reduction}
MARK,REDUCTION
\section{Basics of Modular Reduction}
\index{modular residue}
Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, 
such as factoring.  Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set.  A number $a$ is said to be \textit{reduced}
modulo another number $b$ by finding the remainder of the division $a/b$.  Full integer division with remainder is a topic to be covered 
in~\ref{sec:division}.

Modular reduction is equivalent to solving for $r$ in the following equation.  $a = bq + r$ where $q = \lfloor a/b \rfloor$.  The result 
$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$.  In other vernacular $r$ is known as the 
``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
other forms of residues.  

Modular reductions are normally used to create either finite groups, rings or fields.  The most common usage for performance driven modular reductions 
is in modular exponentiation algorithms.  That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible.  This operation is used in the 
RSA and Diffie-Hellman public key algorithms, for example.  Modular multiplication and squaring also appears as a fundamental operation in 
elliptic curve cryptographic algorithms.  As will be discussed in the subsequent chapter there exist fast algorithms for computing modular 
exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications.  These algorithms will produce partial results in the 
range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms.   They have also been used to create redundancy check 
algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.  

\section{The Barrett Reduction}
The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
division.  Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to 

\begin{equation}
c = a - b \cdot \lfloor a/b \rfloor
\end{equation}

Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper 
targeted the DSP56K processor.}  intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal.  However, 
DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.  
It would take another common optimization to optimize the algorithm.

\subsection{Fixed Point Arithmetic}
The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers.  Fixed
point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were 
fairly slow if not unavailable.   The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit 
integer and a $q$-bit fraction part (\textit{where $p+q = k$}).  

In this system a $k$-bit integer $n$ would actually represent $n/2^q$.  For example, with $q = 4$ the integer $n = 37$ would actually represent the
value $2.3125$.  To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by 
moving the implied decimal point back to where it should be.  For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted 
to fixed point first by multiplying by $2^q$.  Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the 
fixed point representation of $5$.  The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.  

This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
of two fixed point numbers.  Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal.  If $2^q$ is 
equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic.  Using this fact dividing an integer 
$a$ by another integer $b$ can be achieved with the following expression.

\begin{equation}
\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

The precision of the division is proportional to the value of $q$.  If the divisor $b$ is used frequently as is the case with 
modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift.  Both operations
are considerably faster than division on most processors.  

Consider dividing $19$ by $5$.  The correct result is $\lfloor 19/5 \rfloor = 3$.  With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
leads to a product of $19$ which when divided by $2^q$ produces $2$.  However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct.  The value of $2^q$ must be close to or ideally
larger than the dividend.  In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
to work correctly.  Plugging this form of divison into the original equation the following modular residue equation arises.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol.  Using the $\mu$
variable also helps re-inforce the idea that it is meant to be computed once and re-used.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
\end{equation}

Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one.  In the context of Barrett
reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
precision.  

Let $n$ represent the number of digits in $b$.  This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and 
another $n^2$ single precision multiplications to find the residue.  In total $3n^2$ single precision multiplications are required to 
reduce the number.  

For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$.  Consider reducing
$a = 180388626447$ modulo $b$ using the above reduction equation.  The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.

\subsection{Choosing a Radix Point}
Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications.  If that were the best
that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.  
See~\ref{sec:division} for further details.} might as well be used in its place.  The key to optimizing the reduction is to reduce the precision of
the initial multiplication that finds the quotient.  

Let $a$ represent the number of which the residue is sought.  Let $b$ represent the modulus used to find the residue.  Let $m$ represent
the number of digits in $b$.  For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if 
two $m$-digit numbers have been multiplied.  Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer.  Digits below the 
$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$.  Another way to
express this is by re-writing $a$ as two parts.  If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then 
${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$.  Since $a'$ is bound to be less than $b$ the quotient
is bound by $0 \le {a' \over b} < 1$.

Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero.  However, if the digits 
``might as well be zero'' they might as well not be there in the first place.  Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
with the irrelevant digits trimmed.  Now the modular reduction is trimmed to the almost equivalent equation

\begin{equation}
c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
\end{equation}

Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the 
exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$.  If the optimization had not been performed the divisor 
would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two.  The original fixed point quotient can be off
by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
can be off by an additional value of one for a total of at most two.  This implies that 
$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  By first subtracting $b$ times the quotient and then conditionally subtracting 
$b$ once or twice the residue is found.

The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
precision multiplications, ignoring the subtractions required.  In total $2m^2 + m$ single precision multiplications are required to find the residue.  
This is considerably faster than the original attempt.

For example, let $\beta = 10$ represent the radix of the digits.  Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ 
represent the value of which the residue is desired.  In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.  
With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$.  The quotient is then 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$.  Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ 
is found.  

\subsection{Trimming the Quotient}
So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications.  As 
it stands now the algorithm is already fairly fast compared to a full integer division algorithm.  However, there is still room for
optimization.  

After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
half of the product.  It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision 
multiplications.  If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.  
In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.  

The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number.  Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
multiplications would be required.  Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.  

\subsection{Trimming the Residue}
After the quotient has been calculated it is used to reduce the input.  As previously noted the algorithm is not exact and it can be off by a small
multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  If $b$ is $m$ digits than the 
result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
implicitly zero.  

The next optimization arises from this very fact.  Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed.  Similarly the value of $a$ can
be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well.  A multiplication that produces 
only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.  

With both optimizations in place the algorithm is the algorithm Barrett proposed.  It requires $m^2 + 2m - 1$ single precision multiplications which
is considerably faster than the straightforward $3m^2$ method.  

\subsection{The Barrett Algorithm}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
\textbf{Output}.  $a \mbox{ (mod }b\mbox{)}$ \\
\hline \\
Let $m$ represent the number of digits in $b$.  \\
1.  Make a copy of $a$ and store it in $q$.  (\textit{mp\_init\_copy}) \\
2.  $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
\\
Produce the quotient. \\
3.  $q \leftarrow q \cdot \mu$  (\textit{note: only produce digits at or above $m-1$}) \\
4.  $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
\\
Subtract the multiple of modulus from the input. \\
5.  $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
6.  $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
7.  $a \leftarrow a - q$ (\textit{mp\_sub}) \\
\\
Add $\beta^{m+1}$ if a carry occured. \\
8.  If $a < 0$ then (\textit{mp\_cmp\_d}) \\
\hspace{3mm}8.1  $q \leftarrow 1$ (\textit{mp\_set}) \\
\hspace{3mm}8.2  $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
\hspace{3mm}8.3  $a \leftarrow a + q$ \\
\\
Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
9.  While $a \ge b$ do (\textit{mp\_cmp}) \\
\hspace{3mm}9.1  $c \leftarrow a - b$ \\
10.  Clear $q$. \\
11.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce}
\end{figure}

\textbf{Algorithm mp\_reduce.}
This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm.  It is loosely based on algorithm 14.42 of HAC
\cite[pp.  602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}.  The algorithm has several restrictions and assumptions which must 
be adhered to for the algorithm to work.

First the modulus $b$ is assumed to be positive and greater than one.  If the modulus were less than or equal to one than subtracting
a multiple of it would either accomplish nothing or actually enlarge the input.  The input $a$ must be in the range $0 \le a < b^2$ in order
for the quotient to have enough precision.  If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish.  The value of $\mu$ is passed as an argument to this 
algorithm and is assumed to be calculated and stored before the algorithm is used.  

Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position.  An algorithm called 
$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task.  The algorithm is based on $s\_mp\_mul\_digs$ except that
instead of stopping at a given level of precision it starts at a given level of precision.  This optimal algorithm can only be used if the number
of digits in $b$ is very much smaller than $\beta$.  

While it is known that 
$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied 
``borrow'' from the higher digits might leave a negative result.  After the multiple of the modulus has been subtracted from $a$ the residue must be 
fixed up in case it is negative.  The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.  

The while loop at step 9 will subtract $b$ until the residue is less than $b$.  If the algorithm is performed correctly this step is 
performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.

EXAM,bn_mp_reduce.c

The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up.  This essentially halves
the number of single precision multiplications required.  However, the optimization is only safe if $\beta$ is much larger than the number of digits
in the modulus.  In the source code this is evaluated on lines @36,if@ to @44,}@ where algorithm s\_mp\_mul\_high\_digs is used when it is
safe to do so.  

\subsection{The Barrett Setup Algorithm}
In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance.  Ideally this value should be computed once and stored for
future use so that the Barrett algorithm can be used without delay.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_setup}. \\
\textbf{Input}.   mp\_int $a$ ($a > 1$)  \\
\textbf{Output}.  $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
\hline \\
1.  $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot  m}$ (\textit{mp\_2expt}) \\
2.  $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_setup.}
This algorithm computes the reciprocal $\mu$ required for Barrett reduction.  First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot  m}$ which
is equivalent and much faster.  The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.

EXAM,bn_mp_reduce_setup.c

This simple routine calculates the reciprocal $\mu$ required by Barrett reduction.  Note the extended usage of algorithm mp\_div where the variable
which would received the remainder is passed as NULL.  As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the 
remainder to be passed as NULL meaning to ignore the value.  

\section{The Montgomery Reduction}
Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting 
form of reduction in common use.  It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a 
residue times a constant.  However, as perplexing as this may sound the algorithm is relatively simple and very efficient.  

Throughout this entire section the variable $n$ will represent the modulus used to form the residue.  As will be discussed shortly the value of
$n$ must be odd.  The variable $x$ will represent the quantity of which the residue is sought.  Similar to the Barrett algorithm the input
is restricted to $0 \le x < n^2$.  To begin the description some simple number theory facts must be established.

\textbf{Fact 1.}  Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$.  Another way
to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$.  Adding zero will not change the value of the residue.  

\textbf{Fact 2.}  If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$.  Actually
this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to 
multiplication by $k^{-1}$ modulo $n$.  

From these two simple facts the following simple algorithm can be derived.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction}. \\
\textbf{Input}.   Integer $x$, $n$ and $k$ \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $1$ to $k$ do \\
\hspace{3mm}1.1  If $x$ is odd then \\
\hspace{6mm}1.1.1  $x \leftarrow x + n$ \\
\hspace{3mm}1.2  $x \leftarrow x/2$ \\
2.  Return $x$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction}
\end{figure}

The algorithm reduces the input one bit at a time using the two congruencies stated previously.  Inside the loop $n$, which is odd, is
added to $x$ if $x$ is odd.  This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two.  Since
$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$.  Let $r$ represent the 
final result of the Montgomery algorithm.  If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to 
$0 \le r < \lfloor x/2^k \rfloor + n$.  As a result at most a single subtraction is required to get the residue desired.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
\hline $2$ & $x/2 = 1453$ \\
\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
\hline $5$ & $x/2 = 278$ \\
\hline $6$ & $x/2 = 139$ \\
\hline $7$ & $x + n = 396$, $x/2 = 198$ \\
\hline $8$ & $x/2 = 99$ \\
\hline $9$ & $x + n = 356$, $x/2 = 178$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (I)}
\label{fig:MONT1}
\end{figure}

Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$).  The result of 
the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$.  When $r$ is multiplied by $2^9$ modulo $257$ the correct residue 
$r \equiv 158$ is produced.  

Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$.  The current algorithm requires $2k^2$ single precision shifts
and $k^2$ single precision additions.  At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.  
Fortunately there exists an alternative representation of the algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ ($2^k > n$) \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $1$ to $k$ do \\
\hspace{3mm}1.1  If the $t$'th bit of $x$ is one then \\
\hspace{6mm}1.1.1  $x \leftarrow x + 2^tn$ \\
2.  Return $x/2^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified I)}
\end{figure}

This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2.  The number of single
precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|r|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
\hline -- & $5555$ & $1010110110011$ \\
\hline $1$ & $x + 2^{0}n = 5812$ &  $1011010110100$ \\
\hline $2$ & $5812$ & $1011010110100$ \\
\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
\hline $5$ & $8896$ & $10001011000000$ \\
\hline $6$ & $8896$ & $10001011000000$ \\
\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
\hline $8$ & $25344$ & $110001100000000$ \\
\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\
\hline -- & $x/2^k = 178$ & \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (II)}
\label{fig:MONT2}
\end{figure}

Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. 
With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the 
loop.  Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed.  In those iterations the $t$'th bit of $x$ is 
zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.  

\subsection{Digit Based Montgomery Reduction}
Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis.  Consider the
previous algorithm re-written to compute the Montgomery reduction in this new fashion.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ ($\beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1  $x \leftarrow x + \mu n \beta^t$ \\
2.  Return $x/\beta^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified II)}
\end{figure}

The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue.  If the first digit of 
the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit.  This
problem breaks down to solving the following congruency.  

\begin{center}
\begin{tabular}{rcl}
$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\end{tabular}
\end{center}

In each iteration of the loop on step 1 a new value of $\mu$ must be calculated.  The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used 
extensively in this algorithm and should be precomputed.  Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.  

For example, let $\beta = 10$ represent the radix.  Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$.  Let $x = 33$ 
represent the value to reduce.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
\hline --                 & $33$ & --\\
\hline $0$                 & $33 + \mu n = 50$ & $1$ \\
\hline $1$                 & $50 + \mu n \beta = 900$ & $5$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Montgomery Reduction}
\end{figure}

The final result $900$ is then divided by $\beta^k$ to produce the final result $9$.  The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ 
which implies the result is not the modular residue of $x$ modulo $n$.  However, recall that the residue is actually multiplied by $\beta^{-k}$ in
the algorithm.  To get the true residue the value must be multiplied by $\beta^k$.  In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.  

\subsection{Baseline Montgomery Reduction}
The baseline Montgomery reduction algorithm will produce the residue for any size input.  It is designed to be a catch-all algororithm for 
Montgomery reductions.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  $digs \leftarrow 2n.used + 1$ \\
2.  If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
\hspace{3mm}2.1  Use algorithm fast\_mp\_montgomery\_reduce instead. \\
\\
Setup $x$ for the reduction. \\
3.  If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
4.  $x.used \leftarrow digs$ \\
\\
Eliminate the lower $k$ digits. \\
5.  For $ix$ from $0$ to $k - 1$ do \\
\hspace{3mm}5.1  $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.2  $u \leftarrow 0$ \\
\hspace{3mm}5.3  For $iy$ from $0$ to $k - 1$ do \\
\hspace{6mm}5.3.1  $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
\hspace{6mm}5.3.2  $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.3.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.4  While $u > 0$ do \\
\hspace{6mm}5.4.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}5.4.2  $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
\hspace{6mm}5.4.4  $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
\\
Divide by $\beta^k$ and fix up as required. \\
6.  $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
7.  If $x \ge n$ then \\
\hspace{3mm}7.1  $x \leftarrow x - n$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm mp\_montgomery\_reduce.}
This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm.  The algorithm is loosely based
on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop.  The
restrictions on this algorithm are fairly easy to adapt to.  First $0 \le x < n^2$ bounds the input to numbers in the same range as 
for the Barrett algorithm.  Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$.  $\rho$ must be calculated in
advance of this algorithm.  Finally the variable $k$ is fixed and a pseudonym for $n.used$.  

Step 2 decides whether a faster Montgomery algorithm can be used.  It is based on the Comba technique meaning that there are limits on
the size of the input.  This algorithm is discussed in ~COMBARED~.

Step 5 is the main reduction loop of the algorithm.  The value of $\mu$ is calculated once per iteration in the outer loop.  The inner loop
calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits.  Both the addition and
multiplication are performed in the same loop to save time and memory.  Step 5.4 will handle any additional carries that escape the inner loop.

Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications 
in the inner loop.  In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
multiplications.  

EXAM,bn_mp_montgomery_reduce.c

This is the baseline implementation of the Montgomery reduction algorithm.  Lines @30,digs@ to @35,}@ determine if the Comba based
routine can be used instead.  Line @47,mu@ computes the value of $\mu$ for that particular iteration of the outer loop.  

The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop.  The alias $tmpx$ refers to the $ix$'th digit of $x$ and
the alias $tmpn$ refers to the modulus $n$.  

\subsection{Faster ``Comba'' Montgomery Reduction}
MARK,COMBARED

The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
nature of the inner loop.  The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
technique.  The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
a $k \times 1$ product $k$ times. 

The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$.  This means the 
carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit.  The solution as it turns out is very simple.  
Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.  

With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
the speed of the algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
1.  if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
Copy the digits of $x$ into the array $\hat W$ \\
2.  For $ix$ from $0$ to $x.used - 1$ do \\
\hspace{3mm}2.1  $\hat W_{ix} \leftarrow x_{ix}$ \\
3.  For $ix$ from $x.used$ to $2n.used - 1$ do \\
\hspace{3mm}3.1  $\hat W_{ix} \leftarrow 0$ \\
Elimiate the lower $k$ digits. \\
4.  for $ix$ from $0$ to $n.used - 1$ do \\
\hspace{3mm}4.1  $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.2  For $iy$ from $0$ to $n.used - 1$ do \\
\hspace{6mm}4.2.1  $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
\hspace{3mm}4.3  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Propagate carries upwards. \\
5.  for $ix$ from $n.used$ to $2n.used + 1$ do \\
\hspace{3mm}5.1  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Shift right and reduce modulo $\beta$ simultaneously. \\
6.  for $ix$ from $0$ to $n.used + 1$ do \\
\hspace{3mm}6.1  $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
Zero excess digits and fixup $x$. \\
7.  if $x.used > n.used + 1$ then do \\
\hspace{3mm}7.1  for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
\hspace{6mm}7.1.1  $x_{ix} \leftarrow 0$ \\
8.  $x.used \leftarrow n.used + 1$ \\
9.  Clamp excessive digits of $x$. \\
10.  If $x \ge n$ then \\
\hspace{3mm}10.1  $x \leftarrow x - n$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm fast\_mp\_montgomery\_reduce.}
This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique.  It is on most computer platforms significantly
faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}).  The algorithm has the same restrictions
on the input as the baseline reduction algorithm.  An additional two restrictions are imposed on this algorithm.  The number of digits $k$ in the 
the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$.   When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
a modulus of at most $3,556$ bits in length.  

As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product.  It is initially filled with the
contents of $x$ with the excess digits zeroed.  The reduction loop is very similar the to the baseline loop at heart.  The multiplication on step
4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$.  Some multipliers such
as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce.  By performing
a single precision multiplication instead half the amount of time is spent.

Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work.  That is what step
4.3 will do.  In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards.  Note
how the upper bits of those same words are not reduced modulo $\beta$.  This is because those values will be discarded shortly and there is no
point.

Step 5 will propagate the remainder of the carries upwards.  On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
stored in the destination $x$.  

EXAM,bn_fast_mp_montgomery_reduce.c

The $\hat W$ array is first filled with digits of $x$ on line @49,for@ then the rest of the digits are zeroed on line @54,for@.  Both loops share
the same alias variables to make the code easier to read.  

The value of $\mu$ is calculated in an interesting fashion.  First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit.  This
forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision.   Line @101,>>@ fixes the carry 
for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.

The for loop on line @113,for@ propagates the rest of the carries upwards through the columns.  The for loop on line @126,for@ reduces the columns
modulo $\beta$ and shifts them $k$ places at the same time.  The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.  

\subsection{Montgomery Setup}
To calculate the variable $\rho$ a relatively simple algorithm will be required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_setup}. \\
\textbf{Input}.   mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
\textbf{Output}.  $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\hline \\
1.  $b \leftarrow n_0$ \\
2.  If $b$ is even return(\textit{MP\_VAL}) \\
3.  $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\
4.  for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
\hspace{3mm}4.1  $x \leftarrow x \cdot (2 - bx)$ \\
5.  $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_setup} 
\end{figure}

\textbf{Algorithm mp\_montgomery\_setup.}
This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms.  It uses a very interesting trick 
to calculate $1/n_0$ when $\beta$ is a power of two.  

EXAM,bn_mp_montgomery_setup.c

This source code computes the value of $\rho$ required to perform Montgomery reduction.  It has been modified to avoid performing excess
multiplications when $\beta$ is not the default 28-bits.  

\section{The Diminished Radix Algorithm}
The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
or Montgomery methods for certain forms of moduli.  The technique is based on the following simple congruence.

\begin{equation}
(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
\end{equation}

This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive.  It used the fact that if $n = 2^{31}$ and $k=1$ that 
then a x86 multiplier could produce the 62-bit product and use  the ``shrd'' instruction to perform a double-precision right shift.  The proof
of the above equation is very simple.  First write $x$ in the product form.

\begin{equation}
x = qn + r
\end{equation}

Now reduce both sides modulo $(n - k)$.

\begin{equation}
x \equiv qk + r  \mbox{ (mod }(n-k)\mbox{)}
\end{equation}

The variable $n$ reduces modulo $n - k$ to $k$.  By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ 
into the equation the original congruence is reproduced, thus concluding the proof.  The following algorithm is based on this observation.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Diminished Radix Reduction}. \\
\textbf{Input}.   Integer $x$, $n$, $k$ \\
\textbf{Output}.  $x \mbox{ mod } (n - k)$ \\
\hline \\
1.  $q \leftarrow \lfloor x / n \rfloor$ \\
2.  $q \leftarrow k \cdot q$ \\
3.  $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
4.  $x \leftarrow x + q$ \\
5.  If $x \ge (n - k)$ then \\
\hspace{3mm}5.1  $x \leftarrow x - (n - k)$ \\
\hspace{3mm}5.2  Goto step 1. \\
6.  Return $x$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Diminished Radix Reduction}
\label{fig:DR}
\end{figure}

This algorithm will reduce $x$ modulo $n - k$ and return the residue.  If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
once or twice and occasionally three times.  For simplicity sake the value of $x$ is bounded by the following simple polynomial.

\begin{equation} 
0 \le x < n^2 + k^2 - 2nk
\end{equation}

The true bound is  $0 \le x < (n - k - 1)^2$ but this has quite a few more terms.  The value of $q$ after step 1 is bounded by the following.

\begin{equation}
q < n - 2k - k^2/n
\end{equation}

Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero.  The value of $x$ after step 3 is bounded trivially as
$0 \le x < n$.  By step four the sum $x + q$ is bounded by 

\begin{equation}
0 \le q + x < (k + 1)n - 2k^2 - 1
\end{equation}

With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3.  After the second pass it is highly unlike that the
sum in step 4 will exceed $n - k$.  In practice fewer than three passes of the algorithm are required to reduce virtually every input in the 
range $0 \le x < (n - k - 1)^2$.  

\begin{figure}
\begin{small}
\begin{center}
\begin{tabular}{|l|}
\hline
$x = 123456789, n = 256, k = 3$ \\
\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
$q \leftarrow q*k = 1446759$ \\
$x \leftarrow x \mbox{ mod } n = 21$ \\
$x \leftarrow x + q = 1446780$ \\
$x \leftarrow x - (n - k) = 1446527$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 5650$ \\
$q \leftarrow q*k = 16950$ \\
$x \leftarrow x \mbox{ mod } n = 127$ \\
$x \leftarrow x + q = 17077$ \\
$x \leftarrow x - (n - k) = 16824$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 65$ \\
$q \leftarrow q*k = 195$ \\
$x \leftarrow x \mbox{ mod } n = 184$ \\
$x \leftarrow x + q = 379$ \\
$x \leftarrow x - (n - k) = 126$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example Diminished Radix Reduction}
\label{fig:EXDR}
\end{figure}

Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$.  Note that even while $x$
is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast.  In this case only
three passes were required to find the residue $x \equiv 126$.


\subsection{Choice of Moduli}
On the surface this algorithm looks like a very expensive algorithm.  It requires a couple of subtractions followed by multiplication and other
modular reductions.  The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.

Division in general is a very expensive operation to perform.  The one exception is when the division is by a power of the radix of representation used.  
Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right.  Similarly division 
by two (\textit{or powers of two}) is very simple for binary computers to perform.  It would therefore seem logical to choose $n$ of the form $2^p$ 
which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.  

However, there is one operation related to division of power of twos that is even faster than this.  If $n = \beta^p$ then the division may be 
performed by moving whole digits to the right $p$ places.  In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.  
Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.  

Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
modulus'' will refer to a modulus of the form $2^p - k$.  The word ``restricted'' in this case refers to the fact that it is based on the 
$2^p$ logic except $p$ must be a multiple of $lg(\beta)$.  

\subsection{Choice of $k$}
Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
in step 2 is the most expensive operation.  Fortunately the choice of $k$ is not terribly limited.  For all intents and purposes it might
as well be a single digit.  The smaller the value of $k$ is the faster the algorithm will be.  

\subsection{Restricted Diminished Radix Reduction}
The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$.  This algorithm can reduce 
an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}.  The implementation
of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition 
of $x$ and $q$.  The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular 
exponentiations are performed.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_reduce}. \\
\textbf{Input}.   mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
\textbf{Output}.  $x \mbox{ mod } n$ \\
\hline \\
1.  $m \leftarrow n.used$ \\
2.  If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
3.  $\mu \leftarrow 0$ \\
4.  for $i$ from $0$ to $m - 1$ do \\
\hspace{3mm}4.1  $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
\hspace{3mm}4.2  $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  $x_{m} \leftarrow \mu$ \\
6.  for $i$ from $m + 1$ to $x.used - 1$ do \\
\hspace{3mm}6.1  $x_{i} \leftarrow 0$ \\
7.  Clamp excess digits of $x$. \\
8.  If $x \ge n$ then \\
\hspace{3mm}8.1  $x \leftarrow x - n$ \\
\hspace{3mm}8.2  Goto step 3. \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_reduce}
\end{figure}

\textbf{Algorithm mp\_dr\_reduce.}
This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$.  It has similar restrictions to that of the Barrett reduction
with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.  

This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization.  The division by $\beta^m$, multiplication by $k$
and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4.  The division by $\beta^m$ is emulated by accessing
the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position.  After the loop the $m$'th
digit is set to the carry and the upper digits are zeroed.  Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to 
$x$ before the addition of the multiple of the upper half.  

At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required.  First $n$ is subtracted from $x$ and then the algorithm resumes
at step 3.  

EXAM,bn_mp_dr_reduce.c

The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$.  The label on line @49,top:@ is where
the algorithm will resume if further reduction passes are required.  In theory it could be placed at the top of the function however, the size of
the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.  

The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits.  By reading digits from $x$ offset by $m$ digits
a division by $\beta^m$ can be simulated virtually for free.  The loop on line @61,for@ performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
in this algorithm.

By line @68,mu@ the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed.  Similarly by line @71,for@ the 
same pointer will point to the $m+1$'th digit where the zeroes will be placed.  

Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.  
With the same logic at line @82,sub@ the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
as well.  Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
does not need to be checked.

\subsubsection{Setup}
To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required.  This algorithm is not really complicated but provided for
completeness.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_setup}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $k = \beta - n_0$ \\
\hline \\
1.  $k \leftarrow \beta - n_0$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_setup}
\end{figure}

EXAM,bn_mp_dr_setup.c

\subsubsection{Modulus Detection}
Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus.  An integer is said to be
of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $1$ if $n$ is in D.R form, $0$ otherwise \\
\hline
1.  If $n.used < 2$ then return($0$). \\
2.  for $ix$ from $1$ to $n.used - 1$ do \\
\hspace{3mm}2.1  If $n_{ix} \ne \beta - 1$ return($0$). \\
3.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_is\_modulus}
\end{figure}

\textbf{Algorithm mp\_dr\_is\_modulus.}
This algorithm determines if a value is in Diminished Radix form.  Step 1 rejects obvious cases where fewer than two digits are
in the mp\_int.  Step 2 tests all but the first digit to see if they are equal to $\beta - 1$.  If the algorithm manages to get to
step 3 then $n$ must be of Diminished Radix form.

EXAM,bn_mp_dr_is_modulus.c

\subsection{Unrestricted Diminished Radix Reduction}
The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$.  This algorithm
is a straightforward adaptation of algorithm~\ref{fig:DR}.

In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead.  However, this new
algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k}. \\
\textbf{Input}.   mp\_int $a$ and $n$.  mp\_digit $k$  \\
\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
\textbf{Output}.  $a \mbox{ (mod }n\mbox{)}$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  While $a \ge n$ do \\
\hspace{3mm}2.1  $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
\hspace{3mm}2.2  $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
\hspace{3mm}2.3  $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
\hspace{3mm}2.4  $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.5  If $a \ge n$ then do \\
\hspace{6mm}2.5.1  $a \leftarrow a - n$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k.}
This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$.  Division by $2^p$ is emulated with a right
shift which makes the algorithm fairly inexpensive to use.  

EXAM,bn_mp_reduce_2k.c

The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$.  The call to mp\_div\_2d
on line @31,mp_div_2d@ calculates both the quotient $q$ and the remainder $a$ required.  By doing both in a single function call the code size
is kept fairly small.  The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
any multiplications.  

The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are 
positive.  By using the unsigned versions the overhead is kept to a minimum.  

\subsubsection{Unrestricted Setup}
To setup this reduction algorithm the value of $k = 2^p - n$ is required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $k = 2^p - n$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
3.  $x \leftarrow x - n$ (\textit{mp\_sub}) \\
4.  $k \leftarrow x_0$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k\_setup.}
This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k.  By making a temporary variable $x$ equal to $2^p$ a subtraction
is sufficient to solve for $k$.  Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.  

EXAM,bn_mp_reduce_2k_setup.c

\subsubsection{Unrestricted Detection}
An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.

\begin{enumerate}
\item  The number has only one digit.
\item  The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
\end{enumerate}

If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$.   If the input is only
one digit than it will always be of the correct form.  Otherwise all of the bits above the first digit must be one.  This arises from the fact
that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
significant bit.  The resulting sum will be a power of two.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $1$ if of proper form, $0$ otherwise \\
\hline
1.  If $n.used = 0$ then return($0$). \\
2.  If $n.used = 1$ then return($1$). \\
3.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
4.  for $x$ from $lg(\beta)$ to $p$ do \\
\hspace{3mm}4.1  If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
5.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_is\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_is\_2k.}
This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.  

EXAM,bn_mp_reduce_is_2k.c



\section{Algorithm Comparison}
So far three very different algorithms for modular reduction have been discussed.  Each of the algorithms have their own strengths and weaknesses
that makes having such a selection very useful.  The following table sumarizes the three algorithms along with comparisons of work factors.  Since
all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.  

\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
\hline Barrett    & $m^2 + 2m - 1$ & None              & $79$ & $1087$ & $4223$ \\
\hline Montgomery & $m^2 + m$      & $n$ must be odd   & $72$ & $1056$ & $4160$ \\
\hline D.R.       & $2m$           & $n = \beta^m - k$ & $16$ & $64$   & $128$  \\
\hline
\end{tabular}
\end{small}
\end{center}

In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete.  However, in practice since Montgomery
reduction can be written as a single function with the Comba technique it is much faster.  Barrett reduction suffers from the overhead of
calling the half precision multipliers, addition and division by $\beta$ algorithms.

For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice.  The one set of algorithms where Diminished Radix reduction truly
shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}.  In these algorithms
primes of the form $\beta^m - k$ can be found and shared amongst users.  These primes will allow the Diminished Radix algorithm to be used in
modular exponentiation to greatly speed up the operation.



\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
                     & calculates the correct value of $\rho$. \\
                     & \\
$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly.  \\
                     & \\
$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
                     & (\textit{figure~\ref{fig:DR}}) terminates.  Also prove the probability that it will \\
                     & terminate within $1 \le k \le 10$ iterations. \\
                     & \\
\end{tabular}                     


\chapter{Exponentiation}
Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$.  A variant of exponentiation, computed
in a finite field or ring, is called modular exponentiation.  This latter style of operation is typically used in public key 
cryptosystems such as RSA and Diffie-Hellman.  The ability to quickly compute modular exponentiations is of great benefit to any
such cryptosystem and many methods have been sought to speed it up.

\section{Exponentiation Basics}
A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired.  However, as $b$ grows in size
the number of multiplications becomes prohibitive.  Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
with a $1024$-bit key.  Such a calculation could never be completed as it would take simply far too long.

Fortunately there is a very simple algorithm based on the laws of exponents.  Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
are two trivial relationships between the base and the exponent.  Let $b_i$ represent the $i$'th bit of $b$ starting from the least 
significant bit.  If $b$ is a $k$-bit integer than the following equation is true.

\begin{equation}
a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
\end{equation}

By taking the base $a$ logarithm of both sides of the equation the following equation is the result.

\begin{equation}
b = \sum_{i=0}^{k-1}2^i \cdot b_i
\end{equation}

The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
$a^{2^{i+1}}$.  This observation forms the basis of essentially all fast exponentiation algorithms.  It requires $k$ squarings and on average
$k \over 2$ multiplications to compute the result.  This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.

While this current method is a considerable speed up there are further improvements to be made.  For example, the $a^{2^i}$ term does not need to 
be computed in an auxilary variable.  Consider the following equivalent algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Left to Right Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$ and $k$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $k - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^2$ \\
\hspace{3mm}2.2  $c \leftarrow c \cdot a^{b_i}$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Left to Right Exponentiation}
\label{fig:LTOR}
\end{figure}

This algorithm starts from the most significant bit and works towards the least significant bit.  When the $i$'th bit of $b$ is set $a$ is
multiplied against the current product.  In each iteration the product is squared which doubles the exponent of the individual terms of the
product.  

For example, let $b = 101100_2 \equiv 44_{10}$.  The following chart demonstrates the actions of the algorithm.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|}
\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
\hline - & $1$ \\
\hline $5$ & $a$ \\
\hline $4$ & $a^2$ \\
\hline $3$ & $a^4 \cdot a$ \\
\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Left to Right Exponentiation}
\end{figure}

When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation.  This particular algorithm is 
called ``Left to Right'' because it reads the exponent in that order.  All of the exponentiation algorithms that will be presented are of this nature.  

\subsection{Single Digit Exponentiation}
The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit.  It is intended 
to be used when a small power of an input is required (\textit{e.g. $a^5$}).  It is faster than simply multiplying $b - 1$ times for all values of 
$b$ that are greater than three.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_expt\_d}. \\
\textbf{Input}.   mp\_int $a$ and mp\_digit $b$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
2.  $c \leftarrow 1$ (\textit{mp\_set}) \\
3.  for $x$ from 1 to $lg(\beta)$ do \\
\hspace{3mm}3.1  $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
\hspace{3mm}3.2  If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
\hspace{6mm}3.2.1  $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
\hspace{3mm}3.3  $b \leftarrow b << 1$ \\
4.  Clear $g$. \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_expt\_d}
\end{figure}

\textbf{Algorithm mp\_expt\_d.}
This algorithm computes the value of $a$ raised to the power of a single digit $b$.  It uses the left to right exponentiation algorithm to
quickly compute the exponentiation.  It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the 
exponent is a fixed width.  

A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$.  The result is set to the initial value of 
$1$ in the subsequent step.

Inside the loop the exponent is read from the most significant bit first down to the least significant bit.  First $c$ is invariably squared
on step 3.1.  In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$.  The value
of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit.  In effect each
iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.

EXAM,bn_mp_expt_d.c

Line @29,mp_set@ sets the initial value of the result to $1$.  Next the loop on line @31,for@ steps through each bit of the exponent starting from
the most significant down towards the least significant. The invariant squaring operation placed on line @333,mp_sqr@ is performed first.  After 
the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set.  The shift on line
@47,<<@ moves all of the bits of the exponent upwards towards the most significant location.  

\section{$k$-ary Exponentiation}
When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
slower than squaring.  Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$.  Suppose instead it referred to
the $i$'th $k$-bit digit of the exponent of $b$.  For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
computes the same exponentiation.  A group of $k$ bits from the exponent is called a \textit{window}.  That is it is a small window on only a
portion of the entire exponent.  Consider the following modification to the basic left to right exponentiation algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{$k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^{2^k} $ \\
\hspace{3mm}2.2  Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
\hspace{3mm}2.3  $c \leftarrow c \cdot a^g$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{$k$-ary Exponentiation}
\label{fig:KARY}
\end{figure}

The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times.  If the values of $a^g$ for $0 < g < 2^k$ have been
precomputed this algorithm requires only $t$ multiplications and $tk$ squarings.  The table can be generated with $2^{k - 1} - 1$ squarings and
$2^{k - 1} + 1$ multiplications.  This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.  
However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.

Suppose $k = 4$ and $t = 100$.  This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation.  The
original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value.  The total number of squarings
has increased slightly but the number of multiplications has nearly halved.

\subsection{Optimal Values of $k$}
An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$.  The simplest
approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result.  Table~\ref{fig:OPTK} lists optimal values of $k$
for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
\hline $16$ & $2$ & $27$ & $24$ \\
\hline $32$ & $3$ & $49$ & $48$ \\
\hline $64$ & $3$ & $92$ & $96$ \\
\hline $128$ & $4$ & $175$ & $192$ \\
\hline $256$ & $4$ & $335$ & $384$ \\
\hline $512$ & $5$ & $645$ & $768$ \\
\hline $1024$ & $6$ & $1257$ & $1536$ \\
\hline $2048$ & $6$ & $2452$ & $3072$ \\
\hline $4096$ & $7$ & $4808$ & $6144$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for $k$-ary Exponentiation}
\label{fig:OPTK}
\end{figure}

\subsection{Sliding-Window Exponentiation}
A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$.  Essentially
this is a table for all values of $g$ where the most significant bit of $g$ is a one.  However, in order for this to be allowed in the 
algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.  

Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
\hline $16$ & $3$ & $24$ & $27$ \\
\hline $32$ & $3$ & $45$ & $49$ \\
\hline $64$ & $4$ & $87$ & $92$ \\
\hline $128$ & $4$ & $167$ & $175$ \\
\hline $256$ & $5$ & $322$ & $335$ \\
\hline $512$ & $6$ & $628$ & $645$ \\
\hline $1024$ & $6$ & $1225$ & $1257$ \\
\hline $2048$ & $7$ & $2403$ & $2452$ \\
\hline $4096$ & $8$ & $4735$ & $4808$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for Sliding Window Exponentiation}
\label{fig:OPTK2}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  If the $i$'th bit of $b$ is a zero then \\
\hspace{6mm}2.1.1   $c \leftarrow c^2$ \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c \leftarrow c^{2^k}$ \\
\hspace{6mm}2.2.2  Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
\hspace{6mm}2.2.3  $c \leftarrow c \cdot a^g$ \\
\hspace{6mm}2.2.4  $i \leftarrow i - k$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Sliding Window $k$-ary Exponentiation}
\end{figure}

Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent.  While this
algorithm requires the same number of squarings it can potentially have fewer multiplications.  The pre-computed table $a^g$ is also half
the size as the previous table.  

Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms.  The first algorithm will divide the exponent up as 
the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$.  The second algorithm will break the 
exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$.  The single digit $0$ in the second representation are where
a single squaring took place instead of a squaring and multiplication.  In total the first method requires $10$ multiplications and $18$ 
squarings.  The second method requires $8$ multiplications and $18$ squarings.  

In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.  

\section{Modular Exponentiation}

Modular exponentiation is essentially computing the power of a base within a finite field or ring.  For example, computing 
$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation.  Instead of first computing $a^b$ and then reducing it 
modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.  

This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
one of the algorithms presented in ~REDUCTION~.  

Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first.  This algorithm
will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}).  If no inverse exists the algorithm
terminates with an error.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  If $b.sign = MP\_NEG$ then \\
\hspace{3mm}2.1  $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
\hspace{3mm}2.2  $x' \leftarrow \vert x \vert$ \\
\hspace{3mm}2.3  Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
3.  if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
\hspace{3mm}3.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
4.  else \\
\hspace{3mm}4.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_exptmod}
\end{figure}

\textbf{Algorithm mp\_exptmod.}
The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod.  It is a sliding window $k$-ary algorithm 
which uses Barrett reduction to reduce the product modulo $p$.  The second algorithm mp\_exptmod\_fast performs the same operation 
except it uses either Montgomery or Diminished Radix reduction.  The two latter reduction algorithms are clumped in the same exponentiation
algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).  

EXAM,bn_mp_exptmod.c

In order to keep the algorithms in a known state the first step on line @29,if@ is to reject any negative modulus as input.  If the exponent is
negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$.  The temporary variable $tmpG$ is assigned
the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$.  The algorithm will recuse with these new values with a positive
exponent.

If the exponent is positive the algorithm resumes the exponentiation.  Line @63,dr_@ determines if the modulus is of the restricted Diminished Radix 
form.  If it is not line @65,reduce@ attempts to determine if it is of a unrestricted Diminished Radix form.  The integer $dr$ will take on one
of three values.

\begin{enumerate}
\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
\item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
\end{enumerate}

Line @69,if@ determines if the fast modular exponentiation algorithm can be used.  It is allowed if $dr \ne 0$ or if the modulus is odd.  Otherwise,
the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.  

\subsection{Barrett Modular Exponentiation}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  $k \leftarrow lg(x)$ \\
2.  $winsize \leftarrow  \left \lbrace \begin{array}{ll}
                              2 &  \mbox{if }k \le 7 \\
                              3 &  \mbox{if }7 < k \le 36 \\
                              4 &  \mbox{if }36 < k \le 140 \\
                              5 &  \mbox{if }140 < k \le 450 \\
                              6 &  \mbox{if }450 < k \le 1303 \\
                              7 &  \mbox{if }1303 < k \le 3529 \\
                              8 &  \mbox{if }3529 < k \\
                              \end{array} \right .$ \\
3.  Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
4.  Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
5.  $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
\\
Setup the table of small powers of $g$.  First find $g^{2^{winsize}}$ and then all multiples of it. \\
6.  $k \leftarrow 2^{winsize - 1}$ \\
7.  $M_{k} \leftarrow M_1$ \\
8.  for $ix$ from 0 to $winsize - 2$ do \\
\hspace{3mm}8.1  $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr})  \\
\hspace{3mm}8.2  $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
9.  for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
\hspace{3mm}9.1  $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
\hspace{3mm}9.2  $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
10.  $res \leftarrow 1$ \\
\\
Start Sliding Window. \\
11.  $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
12.  Loop \\
\hspace{3mm}12.1  $bitcnt \leftarrow bitcnt - 1$ \\
\hspace{3mm}12.2  If $bitcnt = 0$ then do \\
\hspace{6mm}12.2.1  If $digidx = -1$ goto step 13. \\
\hspace{6mm}12.2.2  $buf \leftarrow x_{digidx}$ \\
\hspace{6mm}12.2.3  $digidx \leftarrow digidx - 1$ \\
\hspace{6mm}12.2.4  $bitcnt \leftarrow lg(\beta)$ \\
Continued on next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
\hspace{3mm}12.3  $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
\hspace{3mm}12.4  $buf \leftarrow buf << 1$ \\
\hspace{3mm}12.5  if $mode = 0$ and $y = 0$ then goto step 12. \\
\hspace{3mm}12.6  if $mode = 1$ and $y = 0$ then do \\
\hspace{6mm}12.6.1  $res \leftarrow res^2$ \\
\hspace{6mm}12.6.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.6.3  Goto step 12. \\
\hspace{3mm}12.7  $bitcpy \leftarrow bitcpy + 1$ \\
\hspace{3mm}12.8  $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
\hspace{3mm}12.9  $mode \leftarrow 2$ \\
\hspace{3mm}12.10  If $bitcpy = winsize$ then do \\
\hspace{6mm}Window is full so perform the squarings and single multiplication. \\
\hspace{6mm}12.10.1  for $ix$ from $0$ to $winsize -1$ do \\
\hspace{9mm}12.10.1.1  $res \leftarrow res^2$ \\
\hspace{9mm}12.10.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.10.2  $res \leftarrow res \cdot M_{bitbuf}$ \\
\hspace{6mm}12.10.3  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}Reset the window. \\
\hspace{6mm}12.10.4  $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
\\
No more windows left.  Check for residual bits of exponent. \\
13.  If $mode = 2$ and $bitcpy > 0$ then do \\
\hspace{3mm}13.1  for $ix$ form $0$ to $bitcpy - 1$ do \\
\hspace{6mm}13.1.1  $res \leftarrow res^2$ \\
\hspace{6mm}13.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}13.1.3  $bitbuf \leftarrow bitbuf << 1$ \\
\hspace{6mm}13.1.4  If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
\hspace{9mm}13.1.4.1  $res \leftarrow res \cdot M_{1}$ \\
\hspace{9mm}13.1.4.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
14.  $y \leftarrow res$ \\
15.  Clear $res$, $mu$ and the $M$ array. \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod (continued)}
\end{figure}

\textbf{Algorithm s\_mp\_exptmod.}
This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$.  It takes advantage of the Barrett reduction
algorithm to keep the product small throughout the algorithm.

The first two steps determine the optimal window size based on the number of bits in the exponent.  The larger the exponent the 
larger the window size becomes.  After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated.  This
table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.  

After the table is allocated the first power of $g$ is found.  Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
the rest of the algorithm more efficient.  The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
times.  The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.

Now that the table is available the sliding window may begin.  The following list describes the functions of all the variables in the window.
\begin{enumerate}
\item The variable $mode$ dictates how the bits of the exponent are interpreted.  
\begin{enumerate}
   \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet.  For example, if the exponent were simply 
         $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit.  In this case bits are ignored until a non-zero bit is found.  
   \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet.  In this mode leading $0$ bits 
         are read and a single squaring is performed.  If a non-zero bit is read a new window is created.  
   \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
         downwards.
\end{enumerate}
\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read.  When it reaches zero a new digit
      is fetched from the exponent.
\item The variable $buf$ holds the currently read digit of the exponent. 
\item The variable $digidx$ is an index into the exponents digits.  It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
\item The variable $bitcpy$ indicates how many bits are in the currently formed window.  When it reaches $winsize$ the window is flushed and
      the appropriate operations performed.
\item The variable $bitbuf$ holds the current bits of the window being formed.  
\end{enumerate}

All of step 12 is the window processing loop.  It will iterate while there are digits available form the exponent to read.  The first step
inside this loop is to extract a new digit if no more bits are available in the current digit.  If there are no bits left a new digit is
read and if there are no digits left than the loop terminates.  

After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
upwards.  In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to 
trailing edges the entire exponent is read from most significant bit to least significant bit.

At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read.  This prevents the 
algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read.  Step 12.6 and 12.7-10 handle
the two cases of $mode = 1$ and $mode = 2$ respectively.  

FIGU,expt_state,Sliding Window State Diagram

By step 13 there are no more digits left in the exponent.  However, there may be partial bits in the window left.  If $mode = 2$ then 
a Left-to-Right algorithm is used to process the remaining few bits.  

EXAM,bn_s_mp_exptmod.c

Lines @31,if@ through @45,}@ determine the optimal window size based on the length of the exponent in bits.  The window divisions are sorted
from smallest to greatest so that in each \textbf{if} statement only one condition must be tested.  For example, by the \textbf{if} statement 
on line @37,if@ the value of $x$ is already known to be greater than $140$.  

The conditional piece of code beginning on line @42,ifdef@ allows the window size to be restricted to five bits.  This logic is used to ensure
the table of precomputed powers of $G$ remains relatively small.  

The for loop on line @60,for@ initializes the $M$ array while lines @71,mp_init@ and @75,mp_reduce@ through @85,}@ initialize the reduction
function that will be used for this modulus.

-- More later.

\section{Quick Power of Two}
Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms.  Recall that a logical shift left $m << k$ is
equivalent to $m \cdot 2^k$.  By this logic when $m = 1$ a quick power of two can be achieved.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_2expt}. \\
\textbf{Input}.   integer $b$ \\
\textbf{Output}.  $a \leftarrow 2^b$ \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
3.  $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
4.  $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_2expt}
\end{figure}

\textbf{Algorithm mp\_2expt.}

EXAM,bn_mp_2expt.c

\chapter{Higher Level Algorithms}

This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package.  These
routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.  

The first section describes a method of integer division with remainder that is universally well known.  It provides the signed division logic
for the package.  The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.  
These algorithms serve mostly to simplify other algorithms where small constants are required.  The last two sections discuss how to manipulate 
various representations of integers.  For example, converting from an mp\_int to a string of character.

\section{Integer Division with Remainder}
\label{sec:division}

Integer division aside from modular exponentiation is the most intensive algorithm to compute.  Like addition, subtraction and multiplication
the basis of this algorithm is the long-hand division algorithm taught to school children.  Throughout this discussion several common variables
will be used.  Let $x$ represent the divisor and $y$ represent the dividend.  Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and 
let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$.  The following simple algorithm will be used to start the discussion.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
\textbf{Input}.   integer $x$ and $y$ \\
\textbf{Output}.  $q = \lfloor y/x\rfloor, r = y - xq$ \\
\hline \\
1.  $q \leftarrow 0$ \\
2.  $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
3.  for $t$ from $n$ down to $0$ do \\
\hspace{3mm}3.1  Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
\hspace{3mm}3.2  $q \leftarrow q + k\beta^t$ \\
\hspace{3mm}3.3  $y \leftarrow y - kx\beta^t$ \\
4.  $r \leftarrow y$ \\
5.  Return($q, r$) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Radix-$\beta$ Integer Division}
\label{fig:raddiv}
\end{figure}

As children we are taught this very simple algorithm for the case of $\beta = 10$.  Almost instinctively several optimizations are taught for which
their reason of existing are never explained.  For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.

To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and 
simultaneously $(k + 1)x\beta^t$ is greater than $y$.  Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have.  The habitual method
used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient.  By only using leading
digits a much simpler division may be used to form an educated guess at what the value must be.  In this case $k = \lfloor 54/23\rfloor = 2$ quickly 
arises as a possible  solution.  Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.  
As a  result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.

Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder 
$y = 841 - 3x\beta = 181$.  Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
remainder $y = 181 - 7x = 20$.  The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since 
$237 \cdot 23 + 20 = 5471$ is true.  

\subsection{Quotient Estimation}
\label{sec:divest}
As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend.  When $p$ leading
digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows.  Technically
speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
dividend and divisor are zero.  

The value of the estimation may off by a few values in either direction and in general is fairly correct.  A simplification \cite[pp. 271]{TAOCPV2}
of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$.  The estimate 
using this technique is never too small.  For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ 
represent the most significant digits of the dividend and divisor respectively.

\textbf{Proof.}\textit{  The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to 
$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger.  For all other 
cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$.  The latter portion of the inequalility
$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values.  Next a series of 
inequalities will prove the hypothesis.

\begin{equation}
y - \hat k x \le y - \hat k x_s\beta^s
\end{equation}

This is trivially true since $x \ge x_s\beta^s$.  Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.  

\begin{equation}
y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
\end{equation}

By simplifying the previous inequality the following inequality is formed.

\begin{equation}
y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
\end{equation}

Subsequently,

\begin{equation}
y_{t-2}\beta^{t-2} + \ldots +  y_0  + x_s\beta^s - \beta^s < x_s\beta^s \le x
\end{equation}

Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof.  \textbf{QED}


\subsection{Normalized Integers}
For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$.  By multiplying both
$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
remainder.  The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
lie in the domain of a single digit.  Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.  

\begin{equation} 
{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} 
\end{equation}

At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.  

\subsection{Radix-$\beta$ Division with Remainder}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div}. \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
1.  If $b = 0$ return(\textit{MP\_VAL}). \\
2.  If $\vert a \vert < \vert b \vert$ then do \\
\hspace{3mm}2.1  $d \leftarrow a$ \\
\hspace{3mm}2.2  $c \leftarrow 0$ \\
\hspace{3mm}2.3  Return(\textit{MP\_OKAY}). \\
\\
Setup the quotient to receive the digits. \\
3.  Grow $q$ to $a.used + 2$ digits. \\
4.  $q \leftarrow 0$ \\
5.  $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
6.  $sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = b.sign \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\\
Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
7.  $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
8.  $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
\\
Find the leading digit of the quotient. \\
9.  $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
10.  $y \leftarrow y \cdot \beta^{n - t}$ \\
11.  While ($x \ge y$) do \\
\hspace{3mm}11.1  $q_{n - t} \leftarrow q_{n - t} + 1$ \\
\hspace{3mm}11.2  $x \leftarrow x - y$ \\
12.  $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
\\
Continued on the next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div} (continued). \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
Now find the remainder fo the digits. \\
13.  for $i$ from $n$ down to $(t + 1)$ do \\
\hspace{3mm}13.1  If $i > x.used$ then jump to the next iteration of this loop. \\
\hspace{3mm}13.2  If $x_{i} = y_{t}$ then \\
\hspace{6mm}13.2.1  $q_{i - t - 1} \leftarrow \beta - 1$ \\
\hspace{3mm}13.3  else \\
\hspace{6mm}13.3.1  $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
\hspace{6mm}13.3.2  $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
\hspace{6mm}13.3.3  $q_{i - t - 1} \leftarrow \hat r$ \\
\hspace{3mm}13.4  $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
\\
Fixup quotient estimation. \\
\hspace{3mm}13.5  Loop \\
\hspace{6mm}13.5.1  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\hspace{6mm}13.5.2  t$1 \leftarrow 0$ \\
\hspace{6mm}13.5.3  t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
\hspace{6mm}13.5.4  $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
\hspace{6mm}13.5.5  t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
\hspace{6mm}13.5.6  If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
\hspace{3mm}13.6  t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
\hspace{3mm}13.7  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{3mm}13.8  $x \leftarrow x - $ t$1$ \\
\hspace{3mm}13.9  If $x.sign = MP\_NEG$ then \\
\hspace{6mm}13.10  t$1 \leftarrow y$ \\
\hspace{6mm}13.11  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{6mm}13.12  $x \leftarrow x + $ t$1$ \\
\hspace{6mm}13.13  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\\
Finalize the result. \\
14.  Clamp excess digits of $q$ \\
15.  $c \leftarrow q, c.sign \leftarrow sign$ \\
16.  $x.sign \leftarrow a.sign$ \\
17.  $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
18.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div (continued)}
\end{figure}
\textbf{Algorithm mp\_div.}
This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor.  The algorithm is a signed
division and will produce a fully qualified quotient and remainder.

First the divisor $b$ must be non-zero which is enforced in step one.  If the divisor is larger than the dividend than the quotient is implicitly 
zero and the remainder is the dividend.  

After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient.  Two unsigned copies of the
divisor $y$ and dividend $x$ are made as well.  The core of the division algorithm is an unsigned division and will only work if the values are
positive.  Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.  
This is performed by shifting both to the left by enough bits to get the desired normalization.  

At this point the division algorithm can begin producing digits of the quotient.  Recall that maximum value of the estimation used is 
$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means.  In this case $y$ is shifted
to the left (\textit{step ten}) so that it has the same number of digits as $x$.  The loop on step eleven will subtract multiples of the 
shifted copy of $y$ until $x$ is smaller.  Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
times to produce the desired leading digit of the quotient.  

Now the remainder of the digits can be produced.  The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
accurately approximate the true quotient digit.  The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.  

Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high.  The next step of the estimation process is
to refine the estimation.  The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
order approximation to adjust the quotient digit.

After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
by optimizing Barrett reduction.}.  Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.  

Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the 
remainder.  An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie 
outside their respective boundaries.  For example, if $t = 0$ or $i \le 1$ then the digits would be undefined.  In those cases the digits should
respectively be replaced with a zero.  

EXAM,bn_mp_div.c

The implementation of this algorithm differs slightly from the pseudo code presented previously.  In this algorithm either of the quotient $c$ or
remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired.  For example, the C code to call the division
algorithm with only the quotient is 

\begin{verbatim}
mp_div(&a, &b, &c, NULL);  /* c = [a/b] */
\end{verbatim}

Lines @108,if@ and @113,if@ handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor 
respectively.  After the two trivial cases all of the temporary variables are initialized.  Line @147,neg@ determines the sign of 
the quotient and line @148,sign@ ensures that both $x$ and $y$ are positive.  

The number of bits in the leading digit is calculated on line @151,norm@.  Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
of precision which when reduced modulo $lg(\beta)$ produces the value of $k$.  In this case $k$ is the number of bits in the leading digit which is
exactly what is required.  For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
them to the left by $lg(\beta) - 1 - k$ bits.

Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively.  These are first used to produce the 
leading digit of the quotient.  The loop beginning on line @184,for@ will produce the remainder of the quotient digits.

The conditional ``continue'' on line @186,continue@ is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
algorithm eliminates multiple non-zero digits in a single iteration.  This ensures that $x_i$ is always non-zero since by definition the digits
above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.  

Lines @214,t1@, @216,t1@ and @222,t2@ through @225,t2@ manually construct the high accuracy estimations by setting the digits of the two mp\_int 
variables directly.  

\section{Single Digit Helpers}

This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants.  All of 
the helper functions assume the single digit input is positive and will treat them as such.

\subsection{Single Digit Addition and Subtraction}

Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction 
algorithms.   As a result these algorithms are subtantially simpler with a slight cost in performance.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = a + b$ \\
\hline \\
1.  $t \leftarrow b$ (\textit{mp\_set}) \\
2.  $c \leftarrow a + t$ \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_add\_d}
\end{figure}

\textbf{Algorithm mp\_add\_d.}
This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.

EXAM,bn_mp_add_d.c

Clever use of the letter 't'.

\subsubsection{Subtraction}
The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.

\subsection{Single Digit Multiplication}
Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
multiplication algorithm.  Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
only has one digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = ab$ \\
\hline \\
1.  $pa \leftarrow a.used$ \\
2.  Grow $c$ to at least $pa + 1$ digits. \\
3.  $oldused \leftarrow c.used$ \\
4.  $c.used \leftarrow pa + 1$ \\
5.  $c.sign \leftarrow a.sign$ \\
6.  $\mu \leftarrow 0$ \\
7.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}7.1  $\hat r \leftarrow \mu + a_{ix}b$ \\
\hspace{3mm}7.2  $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}7.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
8.  $c_{pa} \leftarrow \mu$ \\
9.  for $ix$ from $pa + 1$ to $oldused$ do \\
\hspace{3mm}9.1  $c_{ix} \leftarrow 0$ \\
10.  Clamp excess digits of $c$. \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_d}
\end{figure}
\textbf{Algorithm mp\_mul\_d.}
This algorithm quickly multiplies an mp\_int by a small single digit value.  It is specially tailored to the job and has a minimal of overhead.  
Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.  

EXAM,bn_mp_mul_d.c

In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is 
read from the source.  This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.  

\subsection{Single Digit Division}
Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion.  Since the
divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = \lfloor a / b \rfloor, d = a - cb$ \\
\hline \\
1.  If $b = 0$ then return(\textit{MP\_VAL}).\\
2.  If $b = 3$ then use algorithm mp\_div\_3 instead. \\
3.  Init $q$ to $a.used$ digits.  \\
4.  $q.used \leftarrow a.used$ \\
5.  $q.sign \leftarrow a.sign$ \\
6.  $\hat w \leftarrow 0$ \\
7.  for $ix$ from $a.used - 1$ down to $0$ do \\
\hspace{3mm}7.1  $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
\hspace{3mm}7.2  If $\hat w \ge b$ then \\
\hspace{6mm}7.2.1  $t \leftarrow \lfloor \hat w / b \rfloor$ \\
\hspace{6mm}7.2.2  $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}7.3  else\\
\hspace{6mm}7.3.1  $t \leftarrow 0$ \\
\hspace{3mm}7.4  $q_{ix} \leftarrow t$ \\
8.  $d \leftarrow \hat w$ \\
9.  Clamp excess digits of $q$. \\
10.  $c \leftarrow q$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_d}
\end{figure}
\textbf{Algorithm mp\_div\_d.}
This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach.  Essentially in every iteration of the
algorithm another digit of the dividend is reduced and another digit of quotient produced.  Provided $b < \beta$ the value of $\hat w$
after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.  

If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3.  It replaces the division by three with
a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup.  In essence it is much like the Barrett reduction
from chapter seven.  

EXAM,bn_mp_div_d.c

Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
indicate the respective value is not required.  This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.

The division and remainder on lines @44,/@ and @45,%@ can be replaced often by a single division on most processors.  For example, the 32-bit x86 based 
processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously.  Unfortunately the GCC 
compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.  

\subsection{Single Digit Root Extraction}

Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned.  Algorithms such as the Newton-Raphson approximation 
(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.  

\begin{equation}
x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
\label{eqn:newton}
\end{equation}

In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired.  The derivative of $f(x)$ is 
simply $f'(x) = nx^{n - 1}$.  Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
such as the real numbers.  As a result the root found can be above the true root by few and must be manually adjusted.  Ideally at the end of the 
algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_n\_root}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c^b \le a$ \\
\hline \\
1.  If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  $sign \leftarrow a.sign$ \\
3.  $a.sign \leftarrow MP\_ZPOS$ \\
4.  t$2 \leftarrow 2$ \\
5.  Loop \\
\hspace{3mm}5.1  t$1 \leftarrow $ t$2$ \\
\hspace{3mm}5.2  t$3 \leftarrow $ t$1^{b - 1}$ \\
\hspace{3mm}5.3  t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
\hspace{3mm}5.4  t$2 \leftarrow $ t$2 - a$ \\
\hspace{3mm}5.5  t$3 \leftarrow $ t$3 \cdot b$ \\
\hspace{3mm}5.6  t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
\hspace{3mm}5.7  t$2 \leftarrow $ t$1 - $ t$3$ \\
\hspace{3mm}5.8  If t$1 \ne $ t$2$ then goto step 5.  \\
6.  Loop \\
\hspace{3mm}6.1  t$2 \leftarrow $ t$1^b$ \\
\hspace{3mm}6.2  If t$2 > a$ then \\
\hspace{6mm}6.2.1  t$1 \leftarrow $ t$1 - 1$ \\
\hspace{6mm}6.2.2  Goto step 6. \\
7.  $a.sign \leftarrow sign$ \\
8.  $c \leftarrow $ t$1$ \\
9.  $c.sign \leftarrow sign$  \\
10.  Return(\textit{MP\_OKAY}).  \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_n\_root}
\end{figure}
\textbf{Algorithm mp\_n\_root.}
This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach.  It is partially optimized based on the observation
that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator.  That is at first the denominator is calculated by finding
$x^{b - 1}$.  This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator.  This saves a total of $b - 1$ 
multiplications by t$1$ inside the loop.  

The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
root.  Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.  

EXAM,bn_mp_n_root.c

\section{Random Number Generation}

Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms.  Pollard-Rho 
factoring for example, can make use of random values as starting points to find factors of a composite integer.  In this case the algorithm presented
is solely for simulations and not intended for cryptographic use.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rand}. \\
\textbf{Input}.   An integer $b$ \\
\textbf{Output}.  A pseudo-random number of $b$ digits \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $b \le 0$ return(\textit{MP\_OKAY}) \\
3.  Pick a non-zero random digit $d$. \\
4.  $a \leftarrow a + d$ \\
5.  for $ix$ from 1 to $d - 1$ do \\
\hspace{3mm}5.1  $a \leftarrow a \cdot \beta$ \\
\hspace{3mm}5.2  Pick a random digit $d$. \\
\hspace{3mm}5.3  $a \leftarrow a + d$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rand}
\end{figure}
\textbf{Algorithm mp\_rand.}
This algorithm produces a pseudo-random integer of $b$ digits.  By ensuring that the first digit is non-zero the algorithm also guarantees that the
final result has at least $b$ digits.  It relies heavily on a third-part random number generator which should ideally generate uniformly all of
the integers from $0$ to $\beta - 1$.  

EXAM,bn_mp_rand.c

\section{Formatted Representations}
The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties.  For example, the ability to
be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
into a program.

\subsection{Reading Radix-n Input}
For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to 
printable characters.  For example, when the character ``N'' is read it represents the integer $23$.  The first $16$ characters of the
map are for the common representations up to hexadecimal.  After that they match the ``base64'' encoding scheme which are suitable chosen
such that they are printable.  While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
mediums.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{cc|cc|cc|cc}
\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} &  \textbf{Value} & \textbf{Char} \\
\hline 
0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
8 & 8 & 9 & 9 & 10 & A & 11 & B \\
12 & C & 13 & D & 14 & E & 15 & F \\
16 & G & 17 & H & 18 & I & 19 & J \\
20 & K & 21 & L & 22 & M & 23 & N \\
24 & O & 25 & P & 26 & Q & 27 & R \\
28 & S & 29 & T & 30 & U & 31 & V \\
32 & W & 33 & X & 34 & Y & 35 & Z \\
36 & a & 37 & b & 38 & c & 39 & d \\
40 & e & 41 & f & 42 & g & 43 & h \\
44 & i & 45 & j & 46 & k & 47 & l \\
48 & m & 49 & n & 50 & o & 51 & p \\
52 & q & 53 & r & 54 & s & 55 & t \\
56 & u & 57 & v & 58 & w & 59 & x \\
60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
\hline
\end{tabular}
\end{center}
\caption{Lower ASCII Map}
\label{fig:ASC}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_read\_radix}. \\
\textbf{Input}.   A string $str$ of length $sn$ and radix $r$. \\
\textbf{Output}.  The radix-$\beta$ equivalent mp\_int. \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  $ix \leftarrow 0$ \\
3.  If $str_0 =$ ``-'' then do \\
\hspace{3mm}3.1  $ix \leftarrow ix + 1$ \\
\hspace{3mm}3.2  $sign \leftarrow MP\_NEG$ \\
4.  else \\
\hspace{3mm}4.1  $sign \leftarrow MP\_ZPOS$ \\
5.  $a \leftarrow 0$ \\
6.  for $iy$ from $ix$ to $sn - 1$ do \\
\hspace{3mm}6.1  Let $y$ denote the position in the map of $str_{iy}$. \\
\hspace{3mm}6.2  If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
\hspace{3mm}6.3  $a \leftarrow a \cdot r$ \\
\hspace{3mm}6.4  $a \leftarrow a + y$ \\
7.  If $a \ne 0$ then $a.sign \leftarrow sign$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_read\_radix}
\end{figure}
\textbf{Algorithm mp\_read\_radix.}
This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer.  A minus symbol ``-'' may precede the 
string  to indicate the value is negative, otherwise it is assumed to be positive.  The algorithm will read up to $sn$ characters from the input
and will stop when it reads a character it cannot map the algorithm stops reading characters from the string.  This allows numbers to be embedded
as part of larger input without any significant problem.

EXAM,bn_mp_read_radix.c

\subsection{Generating Radix-$n$ Output}
Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toradix}. \\
\textbf{Input}.   A mp\_int $a$ and an integer $r$\\
\textbf{Output}.  The radix-$r$ representation of $a$ \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}).  \\
3.  $t \leftarrow a$ \\
4.  $str \leftarrow$ ``'' \\
5.  if $t.sign = MP\_NEG$ then \\
\hspace{3mm}5.1  $str \leftarrow str + $ ``-'' \\
\hspace{3mm}5.2  $t.sign = MP\_ZPOS$ \\
6.  While ($t \ne 0$) do \\
\hspace{3mm}6.1  $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
\hspace{3mm}6.2  $t \leftarrow \lfloor t / r \rfloor$ \\
\hspace{3mm}6.3  Look up $d$ in the map and store the equivalent character in $y$. \\
\hspace{3mm}6.4  $str \leftarrow str + y$ \\
7.  If $str_0 = $``$-$'' then \\
\hspace{3mm}7.1  Reverse the digits $str_1, str_2, \ldots str_n$. \\
8.  Otherwise \\
\hspace{3mm}8.1  Reverse the digits $str_0, str_1, \ldots str_n$. \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toradix}
\end{figure}
\textbf{Algorithm mp\_toradix.}
This algorithm computes the radix-$r$ representation of an mp\_int $a$.  The ``digits'' of the representation are extracted by reducing 
successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$.  Note that instead of actually dividing by $r^k$ in
each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration.  As a result a series of trivial $n \times 1$ divisions
are required instead of a series of $n \times k$ divisions.  One design flaw of this approach is that the digits are produced in the reverse order 
(see~\ref{fig:mpradix}).  To remedy this flaw the digits must be swapped or simply ``reversed''.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
\hline $1234$ & -- & -- \\
\hline $123$  & $4$ & ``4'' \\
\hline $12$   & $3$ & ``43'' \\
\hline $1$    & $2$ & ``432'' \\
\hline $0$    & $1$ & ``4321'' \\
\hline
\end{tabular}
\end{center}
\caption{Example of Algorithm mp\_toradix.}
\label{fig:mpradix}
\end{figure}

EXAM,bn_mp_toradix.c

\chapter{Number Theoretic Algorithms}
This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi 
symbol computation.  These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
various Sieve based factoring algorithms.

\section{Greatest Common Divisor}
The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
both $a$ and $b$.  That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
simultaneously.

The most common approach (cite) is to reduce one input modulo another.  That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
$r$ is also divisible by $k$.  The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}1.2  $a \leftarrow b$ \\
\hspace{3mm}1.3  $b \leftarrow r$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (I)}
\label{fig:gcd1}
\end{figure}

This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly.  However, divisions are
relatively expensive operations to perform and should ideally be avoided.  There is another approach based on a similar relationship of 
greatest common divisors.  The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.  
In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}1.2  $b \leftarrow b - a$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (II)}
\label{fig:gcd2}
\end{figure}

\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$.  In other
words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$.  Since both $a$ and $b$ are always 
divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the 
second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof.  \textbf{QED}.

As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful.  Specially if $b$ is much larger than $a$ such that 
$b - a$ is still very much larger than $a$.  A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
not divide the greatest common divisor but will divide $b - a$.  In this case ${b - a} \over p$ is also an integer and still divisible by
the greatest common divisor.

However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.  
Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  $k \leftarrow 0$ \\
2.  While $a$ and $b$ are both divisible by $p$ do \\
\hspace{3mm}2.1  $a \leftarrow \lfloor a / p \rfloor$ \\
\hspace{3mm}2.2  $b \leftarrow \lfloor b / p \rfloor$ \\
\hspace{3mm}2.3  $k \leftarrow k + 1$ \\
3.  While $a$ is divisible by $p$ do \\
\hspace{3mm}3.1  $a \leftarrow \lfloor a / p \rfloor$ \\
4.  While $b$ is divisible by $p$ do \\
\hspace{3mm}4.1  $b \leftarrow \lfloor b / p \rfloor$ \\
5.  While ($b > 0$) do \\
\hspace{3mm}5.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}5.2  $b \leftarrow b - a$ \\
\hspace{3mm}5.3  While $b$ is divisible by $p$ do \\
\hspace{6mm}5.3.1  $b \leftarrow \lfloor b / p \rfloor$ \\
6.  Return($a \cdot p^k$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (III)}
\label{fig:gcd3}
\end{figure}

This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ 
decreases more rapidly.  The first loop on step two removes powers of $p$ that are in common.  A count, $k$, is kept which will present a common
divisor of $p^k$.  After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$.  This means that $p$ can be safely 
divided out of the difference $b - a$ so long as the division leaves no remainder.  

In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often.  It also helps that division by $p$ be easy
to compute.  The ideal choice of $p$ is two since division by two amounts to a right logical shift.  Another important observation is that by
step five both $a$ and $b$ are odd.  Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the 
largest of the pair.

\subsection{Complete Greatest Common Divisor}
The algorithms presented so far cannot handle inputs which are zero or negative.  The following algorithm can handle all input cases properly
and will produce the greatest common divisor.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_gcd}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The greatest common divisor $c = (a, b)$.  \\
\hline \\
1.  If $a = 0$ then \\
\hspace{3mm}1.1  $c \leftarrow \vert b \vert $ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $b = 0$ then \\
\hspace{3mm}2.1  $c \leftarrow \vert a \vert $ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
4.  $k \leftarrow 0$ \\
5.  While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}5.1  $k \leftarrow k + 1$ \\
\hspace{3mm}5.2  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}5.3  $v \leftarrow \lfloor v / 2 \rfloor$ \\
6.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
7.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
8.  While $v.used > 0$ \\
\hspace{3mm}8.1  If $\vert u \vert > \vert v \vert$ then \\
\hspace{6mm}8.1.1  Swap $u$ and $v$. \\
\hspace{3mm}8.2  $v \leftarrow \vert v \vert - \vert u \vert$ \\
\hspace{3mm}8.3  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{6mm}8.3.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
9.  $c \leftarrow u \cdot 2^k$ \\
10.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_gcd}
\end{figure}
\textbf{Algorithm mp\_gcd.}
This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$.  The algorithm was originally based on Algorithm B of
Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain.  In theory it achieves the same asymptotic working time as
Algorithm B and in practice this appears to be true.  

The first two steps handle the cases where either one of or both inputs are zero.  If either input is zero the greatest common divisor is the 
largest input or zero if they are both zero.  If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of 
$a$ and $b$ respectively and the algorithm will proceed to reduce the pair.

Step five will divide out any common factors of two and keep track of the count in the variable $k$.  After this step, two is no longer a
factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even.  Step 
six and seven ensure that the $u$ and $v$ respectively have no more factors of two.  At most only one of the while--loops will iterate since 
they cannot both be even.

By step eight both of $u$ and $v$ are odd which is required for the inner logic.  First the pair are swapped such that $v$ is equal to
or greater than $u$.  This ensures that the subtraction on step 8.2 will always produce a positive and even result.  Step 8.3 removes any
factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.

After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six.  The result
must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.  

EXAM,bn_mp_gcd.c

This function makes use of the macros mp\_iszero and mp\_iseven.  The former evaluates to $1$ if the input mp\_int is equivalent to the 
integer zero otherwise it evaluates to $0$.  The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
it evaluates to $0$.  Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero.  The three 
trivial cases of inputs are handled on lines @23,zero@ through @29,}@.  After those lines the inputs are assumed to be non-zero.

Lines @32,if@ and @36,if@ make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively.  At this point the common factors of two 
must be divided out of the two inputs.  The block starting at line @43,common@ removes common factors of two by first counting the number of trailing
zero bits in both.  The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values.  It is assumed that 
the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than 
entries than are accessible by an ``int'' so this is not a limitation.}.  

At this point there are no more common factors of two in the two values.  The divisions by a power of two on lines @60,div_2d@ and @67,div_2d@ remove 
any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm.  The while loop
on line @72, while@ performs the reduction of the pair until $v$ is equal to zero.  The unsigned comparison and subtraction algorithms are used in
place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.

\section{Least Common Multiple}
The least common multiple of a pair of integers is their product divided by their greatest common divisor.  For two integers $a$ and $b$ the
least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$.  For example, if $a = 2 \cdot 2 \cdot 3 = 12$
and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.

The least common multiple arises often in coding theory as well as number theory.  If two functions have periods of $a$ and $b$ respectively they will
collide, that is be in synchronous states, after only $[ a, b ]$ iterations.  This is why, for example, random number generators based on 
Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).  
Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lcm}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The least common multiple $c = [a, b]$.  \\
\hline \\
1.  $c \leftarrow (a, b)$ \\
2.  $t \leftarrow a \cdot b$ \\
3.  $c \leftarrow \lfloor t / c \rfloor$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lcm}
\end{figure}
\textbf{Algorithm mp\_lcm.}
This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$.  It computes the least common multiple directly by
dividing the product of the two inputs by their greatest common divisor.

EXAM,bn_mp_lcm.c

\section{Jacobi Symbol Computation}
To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg.  What is the name of this?} off which the Jacobi symbol is 
defined.  The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$.  Numerically it is
equivalent to equation \ref{eqn:legendre}.

\textit{-- Tom, don't be an ass, cite your source here...!}

\begin{equation}
a^{(p-1)/2} \equiv \begin{array}{rl}
                              -1 &  \mbox{if }a\mbox{ is a quadratic non-residue.} \\
                              0  &  \mbox{if }a\mbox{ divides }p\mbox{.} \\
                              1  &  \mbox{if }a\mbox{ is a quadratic residue}. 
                              \end{array} \mbox{ (mod }p\mbox{)}
\label{eqn:legendre}                              
\end{equation}

\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
An integer $a$ is a quadratic residue if the following equation has a solution.

\begin{equation}
x^2 \equiv a \mbox{ (mod }p\mbox{)}
\label{eqn:root}
\end{equation}

Consider the following equation.

\begin{equation}
0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
\label{eqn:rooti}
\end{equation}

Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true.  If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
then the quantity in the braces must be zero.  By reduction,

\begin{eqnarray}
\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0  \nonumber \\
\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
x^2 \equiv a \mbox{ (mod }p\mbox{)} 
\end{eqnarray}

As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue.  If $a$ does not divide $p$ and $a$
is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
\begin{equation}
0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
\end{equation}
One of the terms on the right hand side must be zero.  \textbf{QED}

\subsection{Jacobi Symbol}
The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2.  If $p = \prod_{i=0}^n p_i$ then
the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.

\begin{equation}
\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
\end{equation}

By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function.  The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
further details.} will be used to derive an efficient Jacobi symbol algorithm.  Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
following are true.  

\begin{enumerate}
\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. 
\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$.  Otherwise, it equals $-1$.
\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$.  More specifically 
$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.  
\end{enumerate}

Using these facts if $a = 2^k \cdot a'$ then

\begin{eqnarray}
\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
                               = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) 
\label{eqn:jacobi}
\end{eqnarray}

By fact five, 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.

\begin{equation}
\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right )  \cdot (-1)^{(p-1)(a'-1)/4} 
\end{equation}

The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively.  The value of 
$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$.  Using this approach the 
factors of $p$ do not have to be known.  Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the 
Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_jacobi}. \\
\textbf{Input}.   mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
\textbf{Output}.  The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
\hline \\
1.  If $a = 0$ then \\
\hspace{3mm}1.1  $c \leftarrow 0$ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $a = 1$ then \\
\hspace{3mm}2.1  $c \leftarrow 1$ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  $a' \leftarrow a$ \\
4.  $k \leftarrow 0$ \\
5.  While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}5.1  $k \leftarrow k + 1$ \\
\hspace{3mm}5.2  $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
6.  If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
\hspace{3mm}6.1  $s \leftarrow 1$ \\
7.  else \\
\hspace{3mm}7.1  $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
\hspace{3mm}7.2  If $r = 1$ or $r = 7$ then \\
\hspace{6mm}7.2.1  $s \leftarrow 1$ \\
\hspace{3mm}7.3  else \\
\hspace{6mm}7.3.1  $s \leftarrow -1$ \\
8.  If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
\hspace{3mm}8.1  $s \leftarrow -s$ \\
9.  If $a' \ne 1$ then \\
\hspace{3mm}9.1  $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
\hspace{3mm}9.2  $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
10.  $c \leftarrow s$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_jacobi}
\end{figure}
\textbf{Algorithm mp\_jacobi.}
This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three.  The algorithm
is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.  

Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively.  Step five determines the number of two factors in the
input $a$.  If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one.  If $k$ is odd than the term evaluates to one 
if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled 
the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$.  The latter term evaluates to one if both $p$ and $a'$ 
are congruent to one modulo four, otherwise it evaluates to negative one.

By step nine if $a'$ does not equal one a recursion is required.  Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.

EXAM,bn_mp_jacobi.c

As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C 
variable name character. 

The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm.  If the input is non-trivial the algorithm
has to proceed compute the Jacobi.  The variable $s$ is used to hold the current Jacobi product.  Note that $s$ is merely a C ``int'' data type since
the values it may obtain are merely $-1$, $0$ and $1$.  

After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$.  Technically only the least significant
bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same 
processor requirements and neither is faster than the other.

Line @59, if@ through @70, }@ determines the value of $\left ( { 2 \over p } \right )^k$.  If the least significant bit of $k$ is zero than
$k$ is even and the value is one.  Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight.  The value of
$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines @73, if@ through @75, }@.  

Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.  

\textit{-- Comment about default $s$ and such...}

\section{Modular Inverse}
\label{sec:modinv}
The modular inverse of a number actually refers to the modular multiplicative inverse.  Essentially for any integer $a$ such that $(a, p) = 1$ there
exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$.  The integer $b$ is called the multiplicative inverse of $a$ which is
denoted as $b = a^{-1}$.  Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and 
fields of integers.  However, the former will be the matter of discussion.

The simplest approach is to compute the algebraic inverse of the input.  That is to compute $b \equiv a^{\Phi(p) - 1}$.  If $\Phi(p)$ is the 
order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$.  The proof of which is trivial.

\begin{equation}
ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
\end{equation}

However, as simple as this approach may be it has two serious flaws.  It requires that the value of $\Phi(p)$ be known which if $p$ is composite 
requires all of the prime factors.  This approach also is very slow as the size of $p$ grows.  

A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear 
Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.

\begin{equation}
ab + pq = 1
\end{equation}

Where $a$, $b$, $p$ and $q$ are all integers.  If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of 
$a$ modulo $p$.  The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.  
However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place.  The
binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine 
equation.  

\subsection{General Case}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_invmod}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$.  \\
\textbf{Output}.  The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_VAL}). \\
2.  If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
3.  $x \leftarrow \vert a \vert, y \leftarrow b$ \\
4.  If $x_0 \equiv y_0  \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
5.  $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
6.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}6.2  If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}6.2.1  $A \leftarrow A + y$ \\
\hspace{6mm}6.2.2  $B \leftarrow B - x$ \\
\hspace{3mm}6.3  $A \leftarrow \lfloor A / 2 \rfloor$ \\
\hspace{3mm}6.4  $B \leftarrow \lfloor B / 2 \rfloor$ \\
7.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
\hspace{3mm}7.2  If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}7.2.1  $C \leftarrow C + y$ \\
\hspace{6mm}7.2.2  $D \leftarrow D - x$ \\
\hspace{3mm}7.3  $C \leftarrow \lfloor C / 2 \rfloor$ \\
\hspace{3mm}7.4  $D \leftarrow \lfloor D / 2 \rfloor$ \\
8.  If $u \ge v$ then \\
\hspace{3mm}8.1  $u \leftarrow u - v$ \\
\hspace{3mm}8.2  $A \leftarrow A - C$ \\
\hspace{3mm}8.3  $B \leftarrow B - D$ \\
9.  else \\
\hspace{3mm}9.1  $v \leftarrow v - u$ \\
\hspace{3mm}9.2  $C \leftarrow C - A$ \\
\hspace{3mm}9.3  $D \leftarrow D - B$ \\
10.  If $u \ne 0$ goto step 6. \\
11.  If $v \ne 1$ return(\textit{MP\_VAL}). \\
12.  While $C \le 0$ do \\
\hspace{3mm}12.1  $C \leftarrow C + b$ \\
13.  While $C \ge b$ do \\
\hspace{3mm}13.1  $C \leftarrow C - b$ \\
14.  $c \leftarrow C$ \\
15.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\end{figure}
\textbf{Algorithm mp\_invmod.}
This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$.  This algorithm is a variation of the 
extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}.  It has been modified to only compute the modular inverse and not a complete
Diophantine solution.  

If $b \le 0$ than the modulus is invalid and MP\_VAL is returned.  Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
inverse for $a$ and the error is reported.  

The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd.  In this case
the other variables to the Diophantine equation are solved.  The algorithm terminates when $u = 0$ in which case the solution is

\begin{equation}
Ca + Db = v
\end{equation}

If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists.  Otherwise, $C$
is the modular inverse of $a$.  The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie 
within $1 \le a^{-1} < b$.  Step numbers twelve and thirteen adjust the inverse until it is in range.  If the original input $a$ is within $0 < a < p$ 
then only a couple of additions or subtractions will be required to adjust the inverse.

EXAM,bn_mp_invmod.c

\subsubsection{Odd Moduli}

When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse.  In particular by attempting to solve
the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.  

The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed.  This 
optimization will halve the time required to compute the modular inverse.

\section{Primality Tests}

A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself.  For example, $a = 7$ is prime 
since the integers $2 \ldots 6$ do not evenly divide $a$.  By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. 

Prime numbers arise in cryptography considerably as they allow finite fields to be formed.  The ability to determine whether an integer is prime or
not quickly has been a viable subject in cryptography and number theory for considerable time.  The algorithms that will be presented are all
probablistic algorithms in that when they report an integer is composite it must be composite.  However, when the algorithms report an integer is
prime the algorithm may be incorrect.  

As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as 
well be zero.  For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.

\subsection{Trial Division}

Trial division means to attempt to evenly divide a candidate integer by small prime integers.  If the candidate can be evenly divided it obviously
cannot be prime.  By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime.  However, such a test
would require a prohibitive amount of time as $n$ grows.

Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead.  By performing trial division with only a subset
of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime.  However, often it can prove a candidate is not prime.

The benefit of this test is that trial division by small values is fairly efficient.  Specially compared to the other algorithms that will be
discussed shortly.  The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
$1 - {1.12 \over ln(q)}$.  The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range 
$3 \le q \le 100$.  

At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly.  At $q = 90$ further testing is generally not going to 
be of any practical use.  In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate 
approximately $80\%$ of all candidate integers.  The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base.  The 
array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$.  \\
\hline \\
1.  for $ix$ from $0$ to $PRIME\_SIZE$ do \\
\hspace{3mm}1.1  $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
\hspace{3mm}1.2  If $d = 0$ then \\
\hspace{6mm}1.2.1  $c \leftarrow 1$ \\
\hspace{6mm}1.2.2  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow 0$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_is\_divisible}
\end{figure}
\textbf{Algorithm mp\_prime\_is\_divisible.}
This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.  

EXAM,bn_mp_prime_is_divisible.c

The algorithm defaults to a return of $0$ in case an error occurs.  The values in the prime table are all specified to be in the range of a 
mp\_digit.  The table \_\_prime\_tab is defined in the following file.

EXAM,bn_prime_tab.c

Note that there are two possible tables.  When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
upto $1619$ are used.  Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. 

\subsection{The Fermat Test}
The Fermat test is probably one the oldest tests to have a non-trivial probability of success.  It is based on the fact that if $n$ is in 
fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$.  The reason being that if $n$ is prime than the order of
the multiplicative sub group is $n - 1$.  Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to 
$a^1 = a$.  

If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$.  In which case 
it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$.  However, this test is not absolute as it is possible that the order
of a base will divide $n - 1$ which would then be reported as prime.  Such a base yields what is known as a Fermat pseudo-prime.  Several 
integers known as Carmichael numbers will be a pseudo-prime to all valid bases.  Fortunately such numbers are extremely rare as $n$ grows
in size.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_fermat}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$.  \\
\hline \\
1.  $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
2.  If $t = b$ then \\
\hspace{3mm}2.1  $c = 1$ \\
3.  else \\
\hspace{3mm}3.1  $c = 0$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_fermat}
\end{figure}
\textbf{Algorithm mp\_prime\_fermat.}
This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not.  It uses a single modular exponentiation to
determine the result.  

EXAM,bn_mp_prime_fermat.c

\subsection{The Miller-Rabin Test}
The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen 
candidate  integers.  The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the 
value must be equal to $-1$.  The squarings are stopped as soon as $-1$ is observed.  If the value of $1$ is observed first it means that
some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$.  \\
\hline
1.  $a' \leftarrow a - 1$ \\
2.  $r  \leftarrow n1$    \\
3.  $c \leftarrow 0, s  \leftarrow 0$ \\
4.  While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}4.1  $s \leftarrow s + 1$ \\
\hspace{3mm}4.2  $r \leftarrow \lfloor r / 2 \rfloor$ \\
5.  $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
6.  If $y \nequiv \pm 1$ then \\
\hspace{3mm}6.1  $j \leftarrow 1$ \\
\hspace{3mm}6.2  While $j \le (s - 1)$ and $y \nequiv a'$ \\
\hspace{6mm}6.2.1  $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
\hspace{6mm}6.2.2  If $y = 1$ then goto step 8. \\
\hspace{6mm}6.2.3  $j \leftarrow j + 1$ \\
\hspace{3mm}6.3  If $y \nequiv a'$ goto step 8. \\
7.  $c \leftarrow 1$\\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_miller\_rabin}
\end{figure}
\textbf{Algorithm mp\_prime\_miller\_rabin.}
This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$.  It will set $c = 1$ if the algorithm cannot determine
if $b$ is composite or $c = 0$ if $b$ is provably composite.  The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.  

If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not.  Otherwise, the algorithm will
square $y$ upto $s - 1$ times stopping only when $y \equiv -1$.  If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
is provably composite.  If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite.  If $a$ is not provably 
composite then it is \textit{probably} prime.

EXAM,bn_mp_prime_miller_rabin.c




\backmatter
\appendix
\begin{thebibliography}{ABCDEF}
\bibitem[1]{TAOCPV2}
Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998

\bibitem[2]{HAC}
A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996

\bibitem[3]{ROSE}
Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999

\bibitem[4]{COMBA}
Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)

\bibitem[5]{KARA}
A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294

\bibitem[6]{KARAP}
Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002

\bibitem[7]{BARRETT}
Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.

\bibitem[8]{MONT}
P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.

\bibitem[9]{DRMET}
Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories

\bibitem[10]{MMB}
J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89

\bibitem[11]{RSAREF}
R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}

\bibitem[12]{DHREF}
Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976

\bibitem[13]{IEEE}
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)

\bibitem[14]{GMP}
GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}

\bibitem[15]{MPI}
Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}

\bibitem[16]{OPENSSL}
OpenSSL Cryptographic Toolkit, \url{http://openssl.org}

\bibitem[17]{LIP}
Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}

\bibitem[18]{ISOC}
JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''

\bibitem[19]{JAVA}
The Sun Java Website, \url{http://java.sun.com/}

\end{thebibliography}

\input{tommath.ind}

\end{document}

Added libtommath/tommath.tex.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
\usepackage{color}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{layout}
\def\union{\cup}
\def\intersect{\cap}
\def\getsrandom{\stackrel{\rm R}{\gets}}
\def\cross{\times}
\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
\def\catn{$\|$}
\def\divides{\hspace{0.3em} | \hspace{0.3em}}
\def\nequiv{\not\equiv}
\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
\def\lcm{{\rm lcm}}
\def\gcd{{\rm gcd}}
\def\log{{\rm log}}
\def\ord{{\rm ord}}
\def\abs{{\mathit abs}}
\def\rep{{\mathit rep}}
\def\mod{{\mathit\ mod\ }}
\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
\def\Or{{\rm\ or\ }}
\def\And{{\rm\ and\ }}
\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
\def\implies{\Rightarrow}
\def\undefined{{\rm ``undefined"}}
\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
\let\oldphi\phi
\def\phi{\varphi}
\def\Pr{{\rm Pr}}
\newcommand{\str}[1]{{\mathbf{#1}}}
\def\F{{\mathbb F}}
\def\N{{\mathbb N}}
\def\Z{{\mathbb Z}}
\def\R{{\mathbb R}}
\def\C{{\mathbb C}}
\def\Q{{\mathbb Q}}
\definecolor{DGray}{gray}{0.5}
\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\frontmatter
\pagestyle{empty}
\title{Multi--Precision Math}
\author{\mbox{
%\begin{small}
\begin{tabular}{c}
Tom St Denis \\
Algonquin College \\
\\
Mads Rasmussen \\
Open Communications Security \\
\\
Greg Rose \\
QUALCOMM Australia \\
\end{tabular}
%\end{small}
}
}
\maketitle
This text has been placed in the public domain.  This text corresponds to the v0.39 release of the 
LibTomMath project.

\begin{alltt}
Tom St Denis
111 Banning Rd
Ottawa, Ontario
K2L 1C3
Canada

Phone: 1-613-836-3160
Email: [email protected]
\end{alltt}

This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} 
{\em book} macro package and the Perl {\em booker} package.

\tableofcontents
\listoffigures
\chapter*{Prefaces}
When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.  
They ask why I did it and especially why I continue to work on them for free.  The best I can explain it is ``Because I can.''  
Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which 
perhaps explains it better.  I am the first to admit there is not anything that special with what I have done.  Perhaps
others can see that too and then we would have a society to be proud of.  My LibTom projects are what I am doing to give 
back to society in the form of tools and knowledge that can help others in their endeavours.

I started writing this book because it was the most logical task to further my goal of open academia.  The LibTomMath source
code itself was written to be easy to follow and learn from.  There are times, however, where pure C source code does not
explain the algorithms properly.  Hence this book.  The book literally starts with the foundation of the library and works
itself outwards to the more complicated algorithms.  The use of both pseudo--code and verbatim source code provides a duality
of ``theory'' and ``practice'' that the computer science students of the world shall appreciate.  I never deviate too far
from relatively straightforward algebra and I hope that this book can be a valuable learning asset.

This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora
of kind people donating their time, resources and kind words to help support my work.  Writing a text of significant
length (along with the source code) is a tiresome and lengthy process.  Currently the LibTom project is four years old,
comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material.  People like Mads and Greg 
were there at the beginning to encourage me to work well.  It is amazing how timely validation from others can boost morale to 
continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.  

To my many friends whom I have met through the years I thank you for the good times and the words of encouragement.  I hope I
honour your kind gestures with this project.

Open Source.  Open Academia.  Open Minds.

\begin{flushright} Tom St Denis \end{flushright}

\newpage
I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also 
contribute to educate others facing the problem of having to handle big number mathematical calculations.

This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of 
how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about 
the layout and language used.

I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the 
practical aspects of cryptography. 

Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a 
great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up 
multiple precision calculations is often very important since we deal with outdated machine architecture where modular 
reductions, for example, become painfully slow.

This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks 
themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''

\begin{flushright}
Mads Rasmussen

S\~{a}o Paulo - SP

Brazil
\end{flushright}

\newpage
It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about 
Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not 
really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.

At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the 
sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. 
Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.

When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, 
and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close 
friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, 
and I'm pleased to be involved with it.

\begin{flushright}
Greg Rose, Sydney, Australia, June 2003. 
\end{flushright}

\mainmatter
\pagestyle{headings}
\chapter{Introduction}
\section{Multiple Precision Arithmetic}

\subsection{What is Multiple Precision Arithmetic?}
When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
raise or lower the precision of the numbers we are dealing with.  For example, in decimal we almost immediate can 
reason that $7$ times $6$ is $42$.  However, $42$ has two digits of precision as opposed to one digit we started with.  
Further multiplications of say $3$ result in a larger precision result $126$.  In these few examples we have multiple 
precisions for the numbers we are working with.  Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
 of algorithms can be designed to accomodate them.  

By way of comparison a fixed or single precision operation would lose precision on various operations.  For example, in
the decimal system with fixed precision $6 \cdot 7 = 2$.

Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
schools to manually add, subtract, multiply and divide.  

\subsection{The Need for Multiple Precision Arithmetic}
The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
of public-key cryptography algorithms.   Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require 
integers of significant magnitude to resist known cryptanalytic attacks.  For example, at the time of this writing a 
typical RSA modulus would be at least greater than $10^{309}$.  However, modern programming languages such as ISO C \cite{ISOC} and 
Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{|r|c|}
\hline \textbf{Data Type} & \textbf{Range} \\
\hline char  & $-128 \ldots 127$ \\
\hline short & $-32768 \ldots 32767$ \\
\hline long  & $-2147483648 \ldots 2147483647$ \\
\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
\hline
\end{tabular}
\end{center}
\caption{Typical Data Types for the C Programming Language}
\label{fig:ISOC}
\end{figure}

The largest data type guaranteed to be provided by the ISO C programming 
language\footnote{As per the ISO C standard.  However, each compiler vendor is allowed to augment the precision as they 
see fit.}  can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is 
insufficient to accomodate the magnitude required for the problem at hand.  An RSA modulus of magnitude $10^{19}$ could be 
trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, 
rendering any protocol based on the algorithm insecure.  Multiple precision algorithms solve this very problem by 
extending the range of representable integers while using single precision data types.

Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic 
primitives.  Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in 
various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient.  In fact, several 
major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and 
deployment of efficient algorithms.

However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.  
Another auxiliary use of multiple precision integers is high precision floating point data types.  
The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.  
Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE.  Since IEEE 
floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small 
(\textit{23, 48 and 64 bits}).  The mantissa is merely an integer and a multiple precision integer could be used to create
a mantissa of much larger precision than hardware alone can efficiently support.  This approach could be useful where 
scientific applications must minimize the total output error over long calculations.

Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.

\subsection{Benefits of Multiple Precision Arithmetic}
\index{precision}
The benefit of multiple precision representations over single or fixed precision representations is that 
no precision is lost while representing the result of an operation which requires excess precision.  For example, 
the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully.  A multiple 
precision algorithm would augment the precision of the destination to accomodate the result while a single precision system 
would truncate excess bits to maintain a fixed level of precision.

It is possible to implement algorithms which require large integers with fixed precision algorithms.  For example, elliptic
curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum 
size the system will ever need.  Such an approach can lead to vastly simpler algorithms which can accomodate the 
integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard 
processor has an 8 bit accumulator.}.  However, as efficient as such an approach may be, the resulting source code is not
normally very flexible.  It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.

Multiple precision algorithms have the most overhead of any style of arithmetic.  For the the most part the 
overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
platforms.  However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the 
inputs.  That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input 
without the designer's explicit forethought.  This leads to lower cost of ownership for the code as it only has to 
be written and tested once.

\section{Purpose of This Text}
The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.  
That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' 
elements that are neglected by authors of other texts on the subject.  Several well reknowned texts \cite{TAOCPV2,HAC} 
give considerably detailed explanations of the theoretical aspects of algorithms and often very little information 
regarding the practical implementation aspects.  

In most cases how an algorithm is explained and how it is actually implemented are two very different concepts.  For 
example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple 
algorithm for performing multiple precision integer addition.  However, the description lacks any discussion concerning 
the fact that the two integer inputs may be of differing magnitudes.  As a result the implementation is not as simple
as the text would lead people to believe.  Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not 
discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).

Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers 
and fast modular inversion, which we consider practical oversights.  These optimal algorithms are vital to achieve 
any form of useful performance in non-trivial applications.  

To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
package.  As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used 
to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field 
tested and work very well.  The LibTomMath library is freely available on the Internet for all uses and this text 
discusses a very large portion of the inner workings of the library.

The algorithms that are presented will always include at least one ``pseudo-code'' description followed 
by the actual C source code that implements the algorithm.  The pseudo-code can be used to implement the same 
algorithm in other programming languages as the reader sees fit.  

This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch.  Showing
the reader how the algorithms fit together as well as where to start on various taskings.  

\section{Discussion and Notation}
\subsection{Notation}
A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$.  The elements of the array $x$ are said to be the radix $\beta$ digits 
of the integer.  For example, $x = (1,2,3)_{10}$ would represent the integer 
$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.  

\index{mp\_int}
The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well 
as auxilary data required to manipulate the data.  These additional members are discussed further in section 
\ref{sec:MPINT}.  For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be 
synonymous.  When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members 
are present as well.  An expression of the type \textit{variablename.item} implies that it should evaluate to the 
member named ``item'' of the variable.  For example, a string of characters may have a member ``length'' which would 
evaluate to the number of characters in the string.  If the string $a$ equals ``hello'' then it follows that 
$a.length = 5$.  

For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
to solve a given problem.  When an algorithm is described as accepting an integer input it is assumed the input is 
a plain integer with no additional multiple-precision members.  That is, algorithms that use integers as opposed to 
mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management.  These 
algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
precision algorithm to solve the same problem.  

\subsection{Precision Notation}
The variable $\beta$ represents the radix of a single digit of a multiple precision integer and 
must be of the form $q^p$ for $q, p \in \Z^+$.  A single precision variable must be able to represent integers in 
the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range 
$0 \le x < q \beta^2$.  The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the 
carry.  Since all modern computers are binary, it is assumed that $q$ is two.

\index{mp\_digit} \index{mp\_word}
Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent 
a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type.  In 
several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.  
For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to 
the $j$'th digit of a double precision array.  Whenever an expression is to be assigned to a double precision
variable it is assumed that all single precision variables are promoted to double precision during the evaluation.  
Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
precision data type.

For example, if $\beta = 10^2$ a single precision data type may represent a value in the 
range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$.  Let
$a = 23$ and $b = 49$ represent two single precision variables.  The single precision product shall be written
as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
In this particular case, $\hat c = 1127$ and $c = 127$.  The most significant digit of the product would not fit 
in a single precision data type and as a result $c \ne \hat c$.  

\subsection{Algorithm Inputs and Outputs}
Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
as indicated.  The only exception to this rule is when variables have been indicated to be of type mp\_int.  This 
distinction is important as scalars are often used as array indicies and various other counters.  

\subsection{Mathematical Expressions}
The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression 
itself.  For example, $\lfloor 5.7 \rfloor = 5$.  Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
rounded to an integer not less than the expression itself.  For example, $\lceil 5.1 \rceil = 6$.  Typically when 
the $/$ division symbol is used the intention is to perform an integer division with truncation.  For example, 
$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity.  When an expression is written as a 
fraction a real value division is implied, for example ${5 \over 2} = 2.5$.  

The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
of the integer.  For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.  

\subsection{Work Effort}
\index{big-Oh}
To measure the efficiency of the specified algorithms, a modified big-Oh notation is used.  In this system all 
single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.  
That is a single precision addition, multiplication and division are assumed to take the same time to 
complete.  While this is generally not true in practice, it will simplify the discussions considerably.

Some algorithms have slight advantages over others which is why some constants will not be removed in 
the notation.  For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a 
baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work.  In standard big-Oh notation these 
would both be said to be equivalent to $O(n^2)$.  However, 
in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small.  As a 
result small constant factors in the work effort will make an observable difference in algorithm efficiency.

All of the algorithms presented in this text have a polynomial time work level.  That is, of the form 
$O(n^k)$ for $n, k \in \Z^{+}$.  This will help make useful comparisons in terms of the speed of the algorithms and how 
various optimizations will help pay off in the long run.

\section{Exercises}
Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
the discussion at hand.  These exercises are not designed to be prize winning problems, but instead to be thought 
provoking.  Wherever possible the problems are forward minded, stating problems that will be answered in subsequent 
chapters.  The reader is encouraged to finish the exercises as they appear to get a better understanding of the 
subject material.  

That being said, the problems are designed to affirm knowledge of a particular subject matter.  Students in particular
are encouraged to verify they can answer the problems correctly before moving on.

Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
the problem.  However, unlike \cite{TAOCPV2} the problems do not get nearly as hard.  The scoring of these 
exercises ranges from one (the easiest) to five (the hardest).  The following table sumarizes the 
scoring system used.

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|l|}
\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
                            & minutes to solve.  Usually does not involve much computer time \\
                            & to solve. \\
\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
                     & time usage.  Usually requires a program to be written to \\
                     & solve the problem. \\
\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
                     & of work.  Usually involves trivial research and development of \\
                     & new theory from the perspective of a student. \\
\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
                     & of work and research, the solution to which will demonstrate \\
                     & a higher mastery of the subject matter. \\
\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
                     & novice to solve.  Solutions to these problems will demonstrate a \\
                     & complete mastery of the given subject. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Exercise Scoring System}
\end{figure}

Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
devising new theory.  These problems are quick tests to see if the material is understood.  Problems at the second level 
are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer.  These
two levels are essentially entry level questions.  

Problems at the third level are meant to be a bit more difficult than the first two levels.  The answer is often 
fairly obvious but arriving at an exacting solution requires some thought and skill.  These problems will almost always 
involve devising a new algorithm or implementing a variation of another algorithm previously presented.  Readers who can
answer these questions will feel comfortable with the concepts behind the topic at hand.

Problems at the fourth level are meant to be similar to those of the level three questions except they will require 
additional research to be completed.  The reader will most likely not know the answer right away, nor will the text provide 
the exact details of the answer until a subsequent chapter.  

Problems at the fifth level are meant to be the hardest 
problems relative to all the other problems in the chapter.  People who can correctly answer fifth level problems have a 
mastery of the subject matter at hand.

Often problems will be tied together.  The purpose of this is to start a chain of thought that will be discussed in future chapters.  The reader
is encouraged to answer the follow-up problems and try to draw the relevance of problems.

\section{Introduction to LibTomMath}

\subsection{What is LibTomMath?}
LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C.  By portable it 
is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on 
any given platform.  

The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such 
as the Gameboy Advance.  The library is designed to contain enough functionality to be able to develop applications such 
as public key cryptosystems and still maintain a relatively small footprint.

\subsection{Goals of LibTomMath}

Libraries which obtain the most efficiency are rarely written in a high level programming language such as C.  However, 
even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the 
library.  Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM 
processors.  Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window 
exponentiation and Montgomery reduction have been provided to make the library more efficient.  

Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface 
(\textit{API}) has been kept as simple as possible.  Often generic place holder routines will make use of specialized 
algorithms automatically without the developer's specific attention.  One such example is the generic multiplication 
algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication 
based on the magnitude of the inputs and the configuration of the library.  

Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project.  Ideally the library should 
be source compatible with another popular library which makes it more attractive for developers to use.  In this case the
MPI library was used as a API template for all the basic functions.  MPI was chosen because it is another library that fits 
in the same niche as LibTomMath.  Even though LibTomMath uses MPI as the template for the function names and argument 
passing conventions, it has been written from scratch by Tom St Denis.

The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' 
library exists which can be used to teach computer science students how to perform fast and reliable multiple precision 
integer arithmetic.  To this end the source code has been given quite a few comments and algorithm discussion points.  

\section{Choice of LibTomMath}
LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
for more worthy reasons.  Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL 
\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for 
reasons that will be explained in the following sub-sections.

\subsection{Code Base}
The LibTomMath code base is all portable ISO C source code.  This means that there are no platform dependent conditional
segments of code littered throughout the source.  This clean and uncluttered approach to the library means that a
developer can more readily discern the true intent of a given section of source code without trying to keep track of
what conditional code will be used.

The code base of LibTomMath is well organized.  Each function is in its own separate source code file 
which allows the reader to find a given function very quickly.  On average there are $76$ lines of code per source
file which makes the source very easily to follow.  By comparison MPI and LIP are single file projects making code tracing
very hard.  GMP has many conditional code segments which also hinder tracing.  

When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
 which is fairly small compared to GMP (over $250$KiB).  LibTomMath is slightly larger than MPI (which compiles to about 
$50$KiB) but LibTomMath is also much faster and more complete than MPI.

\subsection{API Simplicity}
LibTomMath is designed after the MPI library and shares the API design.  Quite often programs that use MPI will build 
with LibTomMath without change. The function names correlate directly to the action they perform.  Almost all of the 
functions share the same parameter passing convention.  The learning curve is fairly shallow with the API provided 
which is an extremely valuable benefit for the student and developer alike.  

The LIP library is an example of a library with an API that is awkward to work with.  LIP uses function names that are often ``compressed'' to 
illegible short hand.  LibTomMath does not share this characteristic.  

The GMP library also does not return error codes.  Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
are signaled to the host application.  This happens to be the fastest approach but definitely not the most versatile.  In
effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely 
undersireable in many situations.

\subsection{Optimizations}
While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring.  GMP 
and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations.  GMP lacks a few
of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
only had Barrett and Montgomery modular reduction algorithms.}.  

LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
exponentiation.  In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually  
slower than the best libraries such as GMP and OpenSSL by only a small factor.

\subsection{Portability and Stability}
LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler 
(\textit{GCC}).  This means that without changes the library will build without configuration or setting up any 
variables.  LIP and MPI will build ``out of the box'' as well but have numerous known bugs.  Most notably the author of 
MPI has recently stopped working on his library and LIP has long since been discontinued.  

GMP requires a configuration script to run and will not build out of the box.   GMP and LibTomMath are still in active
development and are very stable across a variety of platforms.

\subsection{Choice}
LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
the case study of this text.  Various source files from the LibTomMath project will be included within the text.  However, 
the reader is encouraged to download their own copy of the library to actually be able to work with the library.  

\chapter{Getting Started}
\section{Library Basics}
The trick to writing any useful library of source code is to build a solid foundation and work outwards from it.  First, 
a problem along with allowable solution parameters should be identified and analyzed.  In this particular case the 
inability to accomodate multiple precision integers is the problem.  Futhermore, the solution must be written
as portable source code that is reasonably efficient across several different computer platforms.

After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.  
That is, to implement the lowest level dependencies first and work towards the most abstract functions last.  For example, 
before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
By building outwards from a base foundation instead of using a parallel design methodology the resulting project is 
highly modular.  Being highly modular is a desirable property of any project as it often means the resulting product
has a small footprint and updates are easy to perform.  

Usually when I start a project I will begin with the header files.  I define the data types I think I will need and 
prototype the initial functions that are not dependent on other functions (within the library).  After I 
implement these base functions I prototype more dependent functions and implement them.   The process repeats until
I implement all of the functions I require.  For example, in the case of LibTomMath I implemented functions such as 
mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod().  As an example as to 
why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the 
dependent function mp\_exptmod() was written.  Adding the new multiplication algorithms did not require changes to the 
mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development 
for new algorithms.  This methodology allows new algorithms to be tested in a complete framework with relative ease.

\begin{center}
\begin{figure}[here]
\includegraphics{pics/design_process.ps}
\caption{Design Flow of the First Few Original LibTomMath Functions.}
\label{pic:design_process}
\end{figure}
\end{center}

Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
the source code.  For example, one day I may audit the multipliers and the next day the polynomial basis functions.  

It only makes sense to begin the text with the preliminary data types and support algorithms required as well.  
This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.

\section{What is a Multiple Precision Integer?}
Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot 
be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is 
to use fixed precision data types to create and manipulate multiple precision integers which may represent values 
that are very large.  

As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits.  In the decimal system
the largest single digit value is $9$.  However, by concatenating digits together larger numbers may be represented.  Newly prepended digits 
(\textit{to the left}) are said to be in a different power of ten column.  That is, the number $123$ can be described as having a $1$ in the hundreds 
column, $2$ in the tens column and $3$ in the ones column.  Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$.  Computer based 
multiple precision arithmetic is essentially the same concept.  Larger integers are represented by adjoining fixed 
precision computer words with the exception that a different radix is used.

What most people probably do not think about explicitly are the various other attributes that describe a multiple precision 
integer.  For example, the integer $154_{10}$ has two immediately obvious properties.  First, the integer is positive, 
that is the sign of this particular integer is positive as opposed to negative.  Second, the integer has three digits in 
its representation.  There is an additional property that the integer posesses that does not concern pencil-and-paper 
arithmetic.  The third property is how many digits placeholders are available to hold the integer.  

The human analogy of this third property is ensuring there is enough space on the paper to write the integer.  For example,
if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.  
Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
will not exceed the allowed boundaries.  These three properties make up what is known as a multiple precision 
integer or mp\_int for short.  

\subsection{The mp\_int Structure}
\label{sec:MPINT}
The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer.  The ISO C standard does not provide for 
any such data type but it does provide for making composite data types known as structures.  The following is the structure definition 
used within LibTomMath.

\index{mp\_int}
\begin{figure}[here]
\begin{center}
\begin{small}
%\begin{verbatim}
\begin{tabular}{|l|}
\hline
typedef struct \{ \\
\hspace{3mm}int used, alloc, sign;\\
\hspace{3mm}mp\_digit *dp;\\
\} \textbf{mp\_int}; \\
\hline
\end{tabular}
%\end{verbatim}
\end{small}
\caption{The mp\_int Structure}
\label{fig:mpint}
\end{center}
\end{figure}

The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.

\begin{enumerate}
\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
a given integer.  The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.  

\item The \textbf{alloc} parameter denotes how 
many digits are available in the array to use by functions before it has to increase in size.  When the \textbf{used} count 
of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the 
array to accommodate the precision of the result.  

\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple 
precision integer.  It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits.  The array is maintained in a least 
significant digit order.  As a pencil and paper analogy the array is organized such that the right most digits are stored
first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array.  For example, 
if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then 
it would represent the integer $a + b\beta + c\beta^2 + \ldots$  

\index{MP\_ZPOS} \index{MP\_NEG}
\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).  
\end{enumerate}

\subsubsection{Valid mp\_int Structures}
Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.  
The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().

\begin{enumerate}
\item The value of \textbf{alloc} may not be less than one.  That is \textbf{dp} always points to a previously allocated
array of digits.
\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero.  That is, 
leading zero digits in the most significant positions must be trimmed.
   \begin{enumerate}
   \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
   \end{enumerate}
\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; 
this represents the mp\_int value of zero.
\end{enumerate}

\section{Argument Passing}
A convention of argument passing must be adopted early on in the development of any library.  Making the function 
prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.  
In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int 
structures.  That means that the source (input) operands are placed on the left and the destination (output) on the right.   
Consider the following examples.

\begin{verbatim}
   mp_mul(&a, &b, &c);   /* c = a * b */
   mp_add(&a, &b, &a);   /* a = a + b */
   mp_sqr(&a, &b);       /* b = a * a */
\end{verbatim}

The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
functions and make sense of them.  For example, the first function would read ``multiply a and b and store in c''.

Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
of assignment expressions.  That is, the destination (output) is on the left and arguments (inputs) are on the right.  In 
truth, it is entirely a matter of preference.  In the case of LibTomMath the convention from the MPI library has been 
adopted.  

Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a 
destination.  For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$.  This is an important 
feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.  
However, to implement this feature specific care has to be given to ensure the destination is not modified before the 
source is fully read.

\section{Return Values}
A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them 
to the caller.  By catching runtime errors a library can be guaranteed to prevent undefined behaviour.  However, the end 
developer can still manage to cause a library to crash.  For example, by passing an invalid pointer an application may
fault by dereferencing memory not owned by the application.

In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for 
instance) and memory allocation errors.  It will not check that the mp\_int passed to any function is valid nor 
will it check pointers for validity.  Any function that can cause a runtime error will return an error code as an 
\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).

\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
\begin{figure}[here]
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Value} & \textbf{Meaning} \\
\hline \textbf{MP\_OKAY} & The function was successful \\
\hline \textbf{MP\_VAL}  & One of the input value(s) was invalid \\
\hline \textbf{MP\_MEM}  & The function ran out of heap memory \\
\hline
\end{tabular}
\end{center}
\caption{LibTomMath Error Codes}
\label{fig:errcodes}
\end{figure}

When an error is detected within a function it should free any memory it allocated, often during the initialization of
temporary mp\_ints, and return as soon as possible.  The goal is to leave the system in the same state it was when the 
function was called.  Error checking with this style of API is fairly simple.

\begin{verbatim}
   int err;
   if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
      printf("Error: %s\n", mp_error_to_string(err));
      exit(EXIT_FAILURE);
   }
\end{verbatim}

The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use.  Not all errors are fatal 
and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.

\section{Initialization and Clearing}
The logical starting point when actually writing multiple precision integer functions is the initialization and 
clearing of the mp\_int structures.  These two algorithms will be used by the majority of the higher level algorithms.

Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
the integer.  Often it is optimal to allocate a sufficiently large pre-set number of digits even though
the initial integer will represent zero.  If only a single digit were allocated quite a few subsequent re-allocations
would occur when operations are performed on the integers.  There is a tradeoff between how many default digits to allocate
and how many re-allocations are tolerable.  Obviously allocating an excessive amount of digits initially will waste 
memory and become unmanageable.  

If the memory for the digits has been successfully allocated then the rest of the members of the structure must
be initialized.  Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
to zero.  The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.

\subsection{Initializing an mp\_int}
An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
structure are set to valid values.  The mp\_init algorithm will perform such an action.

\index{mp\_init}
\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Allocate memory and initialize $a$ to a known valid mp\_int state.  \\
\hline \\
1.  Allocate memory for \textbf{MP\_PREC} digits. \\
2.  If the allocation failed return(\textit{MP\_MEM}) \\
3.  for $n$ from $0$ to $MP\_PREC - 1$ do  \\
\hspace{3mm}3.1  $a_n \leftarrow 0$\\
4.  $a.sign \leftarrow MP\_ZPOS$\\
5.  $a.used \leftarrow 0$\\
6.  $a.alloc \leftarrow MP\_PREC$\\
7.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init}
\end{figure}

\textbf{Algorithm mp\_init.}
The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
manipulte it.  It is assumed that the input may not have had any of its members previously initialized which is certainly
a valid assumption if the input resides on the stack.  

Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
the digits is allocated.  If this fails the function returns before setting any of the other members.  The \textbf{MP\_PREC} 
name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} 
used to dictate the minimum precision of newly initialized mp\_int integers.  Ideally, it is at least equal to the smallest
precision number you'll be working with.

Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
heap operations later functions will have to perform in the future.  If \textbf{MP\_PREC} is set correctly the slack 
memory and the number of heap operations will be trivial.

Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
\textbf{alloc} members initialized.  This ensures that the mp\_int will always represent the default state of zero regardless
of the original condition of the input.

\textbf{Remark.}
This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
when the ``to'' keyword is placed between two expressions.  For example, ``for $a$ from $b$ to $c$ do'' means that
a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$.  In each
iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$.  If $b > c$ occured
the loop would not iterate.  By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate 
decrementally.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_init.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure.  It 
is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack.  The 
call to mp\_init() is used only to initialize the members of the structure to a known default state.  

Here we see (line 24) the memory allocation is performed first.  This allows us to exit cleanly and quickly
if there is an error.  If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
was a memory error.  The function XMALLOC is what actually allocates the memory.  Technically XMALLOC is not a function
but a macro defined in ``tommath.h``.  By default, XMALLOC will evaluate to malloc() which is the C library's built--in
memory allocation routine.

In order to assure the mp\_int is in a known state the digits must be set to zero.  On most platforms this could have been
accomplished by using calloc() instead of malloc().  However,  to correctly initialize a integer type to a given value in a 
portable fashion you have to actually assign the value.  The for loop (line 30) performs this required
operation.

After the memory has been successfully initialized the remainder of the members are initialized 
(lines 34 through 35) to their respective default states.  At this point the algorithm has succeeded and
a success code is returned to the calling function.  If this function returns \textbf{MP\_OKAY} it is safe to assume the 
mp\_int structure has been properly initialized and is safe to use with other functions within the library.  

\subsection{Clearing an mp\_int}
When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be 
returned to the application's memory pool with the mp\_clear algorithm.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clear}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  The memory for $a$ shall be deallocated.  \\
\hline \\
1.  If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $a_n \leftarrow 0$ \\
3.  Free the memory allocated for the digits of $a$. \\
4.  $a.used \leftarrow 0$ \\
5.  $a.alloc \leftarrow 0$ \\
6.  $a.sign \leftarrow MP\_ZPOS$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_clear}
\end{figure}

\textbf{Algorithm mp\_clear.}
This algorithm accomplishes two goals.  First, it clears the digits and the other mp\_int members.  This ensures that 
if a developer accidentally re-uses a cleared structure it is less likely to cause problems.  The second goal
is to free the allocated memory.

The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
algorithm will not try to free the memory multiple times.  Cleared mp\_ints are detectable by having a pre-defined invalid 
digit pointer \textbf{dp} setting.

Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The algorithm only operates on the mp\_int if it hasn't been previously cleared.  The if statement (line 25)
checks to see if the \textbf{dp} member is not \textbf{NULL}.  If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
\textbf{NULL} in which case the if statement will evaluate to true.

The digits of the mp\_int are cleared by the for loop (line 27) which assigns a zero to every digit.  Similar to mp\_init()
the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.  

The digits are deallocated off the heap via the XFREE macro.  Similar to XMALLOC the XFREE macro actually evaluates to
a standard C library function.  In this case the free() function.  Since free() only deallocates the memory the pointer
still has to be reset to \textbf{NULL} manually (line 35).  

Now that the digits have been cleared and deallocated the other members are set to their final values (lines 36 and 37).

\section{Maintenance Algorithms}

The previous sections describes how to initialize and clear an mp\_int structure.  To further support operations
that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
able to augment the precision of an mp\_int and 
initialize mp\_ints with differing initial conditions.  

These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
algorithms such as addition, multiplication and modular exponentiation.

\subsection{Augmenting an mp\_int's Precision}
When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire 
result of an operation without loss of precision.  Quite often the size of the array given by the \textbf{alloc} member 
is large enough to simply increase the \textbf{used} digit count.  However, when the size of the array is too small it 
must be re-sized appropriately to accomodate the result.  The mp\_grow algorithm will provide this functionality.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_grow}. \\
\textbf{Input}.   An mp\_int $a$ and an integer $b$. \\
\textbf{Output}.  $a$ is expanded to accomodate $b$ digits. \\
\hline \\
1.  if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
2.  $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
3.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
4.  Re-allocate the array of digits $a$ to size $v$ \\
5.  If the allocation failed then return(\textit{MP\_MEM}). \\
6.  for n from a.alloc to $v - 1$ do  \\
\hspace{+3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.alloc \leftarrow v$ \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_grow}
\end{figure}

\textbf{Algorithm mp\_grow.}
It is ideal to prevent re-allocations from being performed if they are not required (step one).  This is useful to 
prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.  

The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).  
This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.  

It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact.  This is much 
akin to how the \textit{realloc} function from the standard C library works.  Since the newly allocated digits are 
assumed to contain undefined values they are initially set to zero.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

A quick optimization is to first determine if a memory re-allocation is required at all.  The if statement (line 24) checks
if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count.  If the count is not larger than \textbf{alloc}
the function skips the re-allocation part thus saving time.

When a re-allocation is performed it is turned into an optimal request to save time in the future.  The requested digit count is
padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 25).  The XREALLOC function is used
to re-allocate the memory.  As per the other functions XREALLOC is actually a macro which evaluates to realloc by default.  The realloc
function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
the re-allocation.  All	that is left is to clear the newly allocated digits and return.

Note that the re-allocation result is actually stored in a temporary pointer $tmp$.  This is to allow this function to return
an error with a valid pointer.  Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$.  That would
result in a memory leak if XREALLOC ever failed.  

\subsection{Initializing Variable Precision mp\_ints}
Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size 
of input mp\_ints to a given algorithm.  The purpose of algorithm mp\_init\_size is similar to mp\_init except that it 
will allocate \textit{at least} a specified number of digits.  

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_size}. \\
\textbf{Input}.   An mp\_int $a$ and the requested number of digits $b$. \\
\textbf{Output}.  $a$ is initialized to hold at least $b$ digits. \\
\hline \\
1.  $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
2.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
3.  Allocate $v$ digits. \\
4.  for $n$ from $0$ to $v - 1$ do \\
\hspace{3mm}4.1  $a_n \leftarrow 0$ \\
5.  $a.sign \leftarrow MP\_ZPOS$\\
6.  $a.used \leftarrow 0$\\
7.  $a.alloc \leftarrow v$\\
8.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_init\_size}
\end{figure}

\textbf{Algorithm mp\_init\_size.}
This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of 
digits allocated can be controlled by the second input argument $b$.  The input size is padded upwards so it is a 
multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits.  This padding is used to prevent trivial 
allocations from becoming a bottleneck in the rest of the algorithms.

Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero.  This 
particular algorithm is useful if it is known ahead of time the approximate size of the input.  If the approximation is
correct no further memory re-allocations are required to work with the mp\_int.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The number of digits $b$ requested is padded (line 24) by first augmenting it to the next multiple of 
\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result.  If the memory can be successfully allocated the 
mp\_int is placed in a default state representing the integer zero.  Otherwise, the error code \textbf{MP\_MEM} will be 
returned (line 29).  

The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@).  The 
\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set 
to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 33, 34 and 35).  If the function 
returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the 
functions to work with.

\subsection{Multiple Integer Initializations and Clearings}
Occasionally a function will require a series of mp\_int data types to be made available simultaneously.  
The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
statement.  It is essentially a shortcut to multiple initializations.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_multi}. \\
\textbf{Input}.   Variable length array $V_k$ of mp\_int variables of length $k$. \\
\textbf{Output}.  The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
\hline \\
1.  for $n$ from 0 to $k - 1$ do \\
\hspace{+3mm}1.1.  Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
\hspace{+3mm}1.2.  If initialization failed then do \\
\hspace{+6mm}1.2.1.  for $j$ from $0$ to $n$ do \\
\hspace{+9mm}1.2.1.1.  Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
\hspace{+6mm}1.2.2.   Return(\textit{MP\_MEM}) \\
2.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_multi}
\end{figure}

\textbf{Algorithm mp\_init\_multi.}
The algorithm will initialize the array of mp\_int variables one at a time.  If a runtime error has been detected 
(\textit{step 1.2}) all of the previously initialized variables are cleared.  The goal is an ``all or nothing'' 
initialization which allows for quick recovery from runtime errors.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This function intializes a variable length list of mp\_int structure pointers.  However, instead of having the mp\_int
structures in an actual C array they are simply passed as arguments to the function.  This function makes use of the 
``...'' argument syntax of the C programming language.  The list is terminated with a final \textbf{NULL} argument 
appended on the right.  

The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function.  A count
$n$ of succesfully initialized mp\_int structures is maintained (line 48) such that if a failure does occur,
the algorithm can backtrack and free the previously initialized structures (lines 28 to 47).  


\subsection{Clamping Excess Digits}
When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of 
the function instead of checking during the computation.  For example, a multiplication of a $i$ digit number by a 
$j$ digit produces a result of at most $i + j$ digits.  It is entirely possible that the result is $i + j - 1$ 
though, with no final carry into the last position.  However, suppose the destination had to be first expanded 
(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.  
That would be a considerable waste of time since heap operations are relatively slow.

The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
terminates.  This way a single heap operation (\textit{at most}) is required.  However, if the result was not checked
there would be an excess high order zero digit.  

For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$.  The leading zero digit 
will not contribute to the precision of the result.  In fact, through subsequent operations more leading zero digits would
accumulate to the point the size of the integer would be prohibitive.  As a result even though the precision is very 
low the representation is excessively large.  

The mp\_clamp algorithm is designed to solve this very problem.  It will trim high-order zeros by decrementing the 
\textbf{used} count until a non-zero most significant digit is found.  Also in this system, zero is considered to be a 
positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to 
\textbf{MP\_ZPOS}.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clamp}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Any excess leading zero digits of $a$ are removed \\
\hline \\
1.  while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
\hspace{+3mm}1.1  $a.used \leftarrow a.used - 1$ \\
2.  if $a.used = 0$ then do \\
\hspace{+3mm}2.1  $a.sign \leftarrow MP\_ZPOS$ \\
\hline \\
\end{tabular}
\end{center}
\caption{Algorithm mp\_clamp}
\end{figure}

\textbf{Algorithm mp\_clamp.}
As can be expected this algorithm is very simple.  The loop on step one is expected to iterate only once or twice at
the most.  For example, this will happen in cases where there is not a carry to fill the last position.  Step two fixes the sign for 
when all of the digits are zero to ensure that the mp\_int is valid at all times.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Note on line 28 how to test for the \textbf{used} count is made on the left of the \&\& operator.  In the C programming
language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails.  This is 
important since if the \textbf{used} is zero the test on the right would fetch below the array.  That is obviously 
undesirable.  The parenthesis on line 31 is used to make sure the \textbf{used} count is decremented and not
the pointer ``a''.  

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
                     & \\
$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations.  \\
                     & \\
$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
                     & encryption when $\beta = 2^{28}$.  \\
                     & \\
$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp.  What does it prevent? \\
                     & \\
$\left [ 1 \right ]$ & Give an example of when the algorithm  mp\_init\_copy might be useful. \\
                     & \\
\end{tabular}


%%%
% CHAPTER FOUR
%%%

\chapter{Basic Operations}

\section{Introduction}
In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
mp\_int structures.  This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low 
level basis of the entire library.  While these algorithm are relatively trivial it is important to understand how they
work before proceeding since these algorithms will be used almost intrinsically in the following chapters.

The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
represent.   

\section{Assigning Values to mp\_int Structures}
\subsection{Copying an mp\_int}
Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
a copy for the purposes of this text.  The copy of the mp\_int will be a separate entity that represents the same
value as the mp\_int it was copied from.  The mp\_copy algorithm provides this functionality. 

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_copy}. \\
\textbf{Input}.  An mp\_int $a$ and $b$. \\
\textbf{Output}.  Store a copy of $a$ in $b$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to $a.used$ digits.  (\textit{mp\_grow}) \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $b_{n} \leftarrow a_{n}$ \\
3.  for $n$ from $a.used$ to $b.used - 1$ do \\
\hspace{3mm}3.1  $b_{n} \leftarrow 0$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $b.sign \leftarrow a.sign$ \\
6.  return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_copy}
\end{figure}

\textbf{Algorithm mp\_copy.}
This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
represent the same integer as the mp\_int $a$.  The mp\_int $b$ shall be a complete and distinct copy of the 
mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.

If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow 
algorithm.  The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
and three).  The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
$b$.

\textbf{Remark.}  This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
text.  The error return codes of other algorithms are not explicitly checked in the pseudo-code presented.  For example, in 
step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded.  Text space is 
limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
the error code itself.  However, the C code presented will demonstrate all of the error handling logic required to 
implement the pseudo-code.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
mp\_int structures passed to a function are one and the same.  For this case it is optimal to return immediately without 
copying digits (line 25).  

The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$.  If $b.alloc$ is less than
$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 30 to 33).  In order to
simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
of the mp\_ints $a$ and $b$ respectively.  These aliases (lines 43 and 46) allow the compiler to access the digits without first dereferencing the
mp\_int pointers and then subsequently the pointer to the digits.  

After the aliases are established the digits from $a$ are copied into $b$ (lines 49 to 51) and then the excess 
digits of $b$ are set to zero (lines 54 to 56).  Both ``for'' loops make use of the pointer aliases and in 
fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits.  This optimization 
allows the alias to stay in a machine register fairly easy between the two loops.

\textbf{Remarks.}  The use of pointer aliases is an implementation methodology first introduced in this function that will
be used considerably in other functions.  Technically, a pointer alias is simply a short hand alias used to lower the 
number of pointer dereferencing operations required to access data.  For example, a for loop may resemble

\begin{alltt}
for (x = 0; x < 100; x++) \{
    a->num[4]->dp[x] = 0;
\}
\end{alltt}

This could be re-written using aliases as 

\begin{alltt}
mp_digit *tmpa;
a = a->num[4]->dp;
for (x = 0; x < 100; x++) \{
    *a++ = 0;
\}
\end{alltt}

In this case an alias is used to access the 
array of digits within an mp\_int structure directly.  It may seem that a pointer alias is strictly not required 
as a compiler may optimize out the redundant pointer operations.  However, there are two dominant reasons to use aliases.

The first reason is that most compilers will not effectively optimize pointer arithmetic.  For example, some optimizations 
may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC).  Also some optimizations may 
work for GCC and not MSVC.  As such it is ideal to find a common ground for as many compilers as possible.  Pointer 
aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code 
stands a better chance of being faster.

The second reason is that pointer aliases often can make an algorithm simpler to read.  Consider the first ``for'' 
loop of the function mp\_copy() re-written to not use pointer aliases.

\begin{alltt}
    /* copy all the digits */
    for (n = 0; n < a->used; n++) \{
      b->dp[n] = a->dp[n];
    \}
\end{alltt}

Whether this code is harder to read depends strongly on the individual.  However, it is quantifiably slightly more 
complicated as there are four variables within the statement instead of just two.

\subsubsection{Nested Statements}
Another commonly used technique in the source routines is that certain sections of code are nested.  This is used in
particular with the pointer aliases to highlight code phases.  For example, a Comba multiplier (discussed in chapter six)
will typically have three different phases.  First the temporaries are initialized, then the columns calculated and 
finally the carries are propagated.  In this example the middle column production phase will typically be nested as it
uses temporary variables and aliases the most.

The nesting also simplies the source code as variables that are nested are only valid for their scope.  As a result
the various temporary variables required do not propagate into other sections of code.


\subsection{Creating a Clone}
Another common operation is to make a local temporary copy of an mp\_int argument.  To initialize an mp\_int 
and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone.  This is 
useful within functions that need to modify an argument but do not wish to actually modify the original copy.  The 
mp\_init\_copy algorithm has been designed to help perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_copy}. \\
\textbf{Input}.   An mp\_int $a$ and $b$\\
\textbf{Output}.  $a$ is initialized to be a copy of $b$. \\
\hline \\
1.  Init $a$.  (\textit{mp\_init}) \\
2.  Copy $b$ to $a$.  (\textit{mp\_copy}) \\
3.  Return the status of the copy operation. \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_copy}
\end{figure}

\textbf{Algorithm mp\_init\_copy.}
This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it.  As 
such this algorithm will perform two operations in one step.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}.  Note that 
\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
and \textbf{a} will be left intact.  

\section{Zeroing an Integer}
Reseting an mp\_int to the default state is a common step in many algorithms.  The mp\_zero algorithm will be the algorithm used to
perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_zero}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Zero the contents of $a$ \\
\hline \\
1.  $a.used \leftarrow 0$ \\
2.  $a.sign \leftarrow$ MP\_ZPOS \\
3.  for $n$ from 0 to $a.alloc - 1$ do \\
\hspace{3mm}3.1  $a_n \leftarrow 0$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_zero}
\end{figure}

\textbf{Algorithm mp\_zero.}
This algorithm simply resets a mp\_int to the default state.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the 
\textbf{sign} variable is set to \textbf{MP\_ZPOS}.

\section{Sign Manipulation}
\subsection{Absolute Value}
With the mp\_int representation of an integer, calculating the absolute value is trivial.  The mp\_abs algorithm will compute
the absolute value of an mp\_int.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_abs}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = \vert a \vert$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  $b.sign \leftarrow MP\_ZPOS$ \\
4.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_abs}
\end{figure}

\textbf{Algorithm mp\_abs.}
This algorithm computes the absolute of an mp\_int input.  First it copies $a$ over $b$.  This is an example of an
algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful.  This allows,
for instance, the developer to pass the same mp\_int as the source and destination to this function without addition 
logic to handle it.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This fairly trivial algorithm first eliminates non--required duplications (line 28) and then sets the
\textbf{sign} flag to \textbf{MP\_ZPOS}.

\subsection{Integer Negation}
With the mp\_int representation of an integer, calculating the negation is also trivial.  The mp\_neg algorithm will compute
the negative of an mp\_int input.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_neg}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = -a$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
4.  If $a.sign = MP\_ZPOS$ then do \\
\hspace{3mm}4.1  $b.sign = MP\_NEG$. \\
5.  else do \\
\hspace{3mm}5.1  $b.sign = MP\_ZPOS$. \\
6.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_neg}
\end{figure}

\textbf{Algorithm mp\_neg.}
This algorithm computes the negation of an input.  First it copies $a$ over $b$.  If $a$ has no used digits then
the algorithm returns immediately.  Otherwise it flips the sign flag and stores the result in $b$.  Note that if 
$a$ had no digits then it must be positive by definition.  Had step three been omitted then the algorithm would return
zero as negative.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Like mp\_abs() this function avoids non--required duplications (line 22) and then sets the sign.  We
have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}.  If the mp\_int is zero
than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.

\section{Small Constants}
\subsection{Setting Small Constants}
Often a mp\_int must be set to a relatively small value such as $1$ or $2$.  For these cases the mp\_set algorithm is useful.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set}. \\
\textbf{Input}.   An mp\_int $a$ and a digit $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}). \\
2.  $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
3.  $a.used \leftarrow  \left \lbrace \begin{array}{ll}
                              1 &  \mbox{if }a_0 > 0 \\
                              0 &  \mbox{if }a_0 = 0 
                              \end{array} \right .$ \\
\hline                              
\end{tabular}
\end{center}
\caption{Algorithm mp\_set}
\end{figure}

\textbf{Algorithm mp\_set.}
This algorithm sets a mp\_int to a small single digit value.  Step number 1 ensures that the integer is reset to the default state.  The
single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_set.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

First we zero (line 21) the mp\_int to make sure that the other members are initialized for a 
small positive constant.  mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
is zero.  Next we set the digit and reduce it modulo $\beta$ (line 22).  After this step we have to 
check if the resulting digit is zero or not.  If it is not then we set the \textbf{used} count to one, otherwise
to zero.

We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with 
$2^k - 1$ will perform the same operation.

One important limitation of this function is that it will only set one digit.  The size of a digit is not fixed, meaning source that uses 
this function should take that into account.  Only trivially small constants can be set using this function.

\subsection{Setting Large Constants}
To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal.  It accepts a ``long''
data type as input and will always treat it as a 32-bit integer.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set\_int}. \\
\textbf{Input}.   An mp\_int $a$ and a ``long'' integer $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}) \\
2.  for $n$ from 0 to 7 do \\
\hspace{3mm}2.1  $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
\hspace{3mm}2.2  $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
\hspace{3mm}2.3  $a_0 \leftarrow a_0 + u$ \\
\hspace{3mm}2.4  $a.used \leftarrow a.used + 1$ \\
3.  Clamp excess used digits (\textit{mp\_clamp}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_set\_int}
\end{figure}

\textbf{Algorithm mp\_set\_int.}
The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the 
mp\_int.  Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions.  In step 2.2 the
next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is 
incremented to reflect the addition.  The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
zero digits used and the newly added four bits would be ignored.

Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes.  The weird
addition on line 39 ensures that the newly added in bits are added to the number of digits.  While it may not 
seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 28 
as well as the  call to mp\_clamp() on line 41.  Both functions will clamp excess leading digits which keeps 
the number of used digits low.

\section{Comparisons}
\subsection{Unsigned Comparisions}
Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers.  For example,
to compare $1,234$ to $1,264$ the digits are extracted by their positions.  That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude 
positions.  If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.  

The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
mp\_int variables alone.  It will ignore the sign of the two inputs.  Such a function is useful when an absolute comparison is required or if the 
signs are known to agree in advance.

To facilitate working with the results of the comparison functions three constants are required.  

\begin{figure}[here]
\begin{center}
\begin{tabular}{|r|l|}
\hline \textbf{Constant} & \textbf{Meaning} \\
\hline \textbf{MP\_GT} & Greater Than \\
\hline \textbf{MP\_EQ} & Equal To \\
\hline \textbf{MP\_LT} & Less Than \\
\hline
\end{tabular}
\end{center}
\caption{Comparison Return Codes}
\end{figure}

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp\_mag}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$.  \\
\textbf{Output}.  Unsigned comparison results ($a$ to the left of $b$). \\
\hline \\
1.  If $a.used > b.used$ then return(\textit{MP\_GT}) \\
2.  If $a.used < b.used$ then return(\textit{MP\_LT}) \\
3.  for n from $a.used - 1$ to 0 do \\
\hspace{+3mm}3.1  if $a_n > b_n$ then return(\textit{MP\_GT}) \\
\hspace{+3mm}3.2  if $a_n < b_n$ then return(\textit{MP\_LT}) \\
4.  Return(\textit{MP\_EQ}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp\_mag}
\end{figure}

\textbf{Algorithm mp\_cmp\_mag.}
By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$.  The first two steps compare the number of digits used in both $a$ and $b$.  
Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.  
If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.  

By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
the zero'th digit.  If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The two if statements (lines 25 and 29) compare the number of digits in the two inputs.  These two are 
performed before all of the digits are compared since it is a very cheap test to perform and can potentially save 
considerable time.  The implementation given is also not valid without those two statements.  $b.alloc$ may be 
smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.



\subsection{Signed Comparisons}
Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}).  Based on an unsigned magnitude 
comparison a trivial signed comparison algorithm can be written.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  Signed Comparison Results ($a$ to the left of $b$) \\
\hline \\
1.  if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
2.  if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
3.  if $a.sign = MP\_NEG$ then \\
\hspace{+3mm}3.1  Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
4   Otherwise \\
\hspace{+3mm}4.1  Return the unsigned comparison of $a$ and $b$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp}
\end{figure}

\textbf{Algorithm mp\_cmp.}
The first two steps compare the signs of the two inputs.  If the signs do not agree then it can return right away with the appropriate 
comparison code.  When the signs are equal the digits of the inputs must be compared to determine the correct result.  In step 
three the unsigned comparision flips the order of the arguments since they are both negative.  For instance, if $-a > -b$ then 
$\vert a \vert < \vert b \vert$.  Step number four will compare the two when they are both positive.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The two if statements (lines 23 and 24) perform the initial sign comparison.  If the signs are not the equal then which ever
has the positive sign is larger.   The inputs are compared (line 32) based on magnitudes.  If the signs were both 
negative then the unsigned comparison is performed in the opposite direction (line 34).  Otherwise, the signs are assumed to 
be both positive and a forward direction unsigned comparison is performed.

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
                     & \\
$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits  \\
                     & of two random digits (of equal magnitude) before a difference is found. \\
                     & \\
$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based  \\
                     & on the observations made in the previous problem. \\
                     &
\end{tabular}

\chapter{Basic Arithmetic}
\section{Introduction}
At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been 
established.  The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms.  These 
algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms.  It is very important 
that these algorithms are highly optimized.  On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms 
which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.  

All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right 
logical shifts respectively.  A logical shift is analogous to sliding the decimal point of radix-10 representations.  For example, the real 
number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).  
Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.  
For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.

One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
from the number.  For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$.  However, with a logical shift the 
result is $110_2$.  

\section{Addition and Subtraction}
In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus.  For example, with 32-bit integers
$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$  since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.  
As a result subtraction can be performed with a trivial series of logical operations and an addition.

However, in multiple precision arithmetic negative numbers are not represented in the same way.  Instead a sign flag is used to keep track of the
sign of the integer.  As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or 
subtraction algorithms with the sign fixed up appropriately.

The lower level algorithms will add or subtract integers without regard to the sign flag.  That is they will add or subtract the magnitude of
the integers respectively.

\subsection{Low Level Addition}
An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers.  That is to add the 
trailing digits first and propagate the resulting carry upwards.  Since this is a lower level algorithm the name will have a ``s\_'' prefix.  
Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.

\newpage
\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
\hline \\
1.  if $a.used > b.used$ then \\
\hspace{+3mm}1.1  $min \leftarrow b.used$ \\
\hspace{+3mm}1.2  $max \leftarrow a.used$ \\
\hspace{+3mm}1.3  $x   \leftarrow a$ \\
2.  else  \\
\hspace{+3mm}2.1  $min \leftarrow a.used$ \\
\hspace{+3mm}2.2  $max \leftarrow b.used$ \\
\hspace{+3mm}2.3  $x   \leftarrow b$ \\
3.  If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\
5.  $c.used \leftarrow max + 1$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{+3mm}7.1  $c_n \leftarrow a_n + b_n + u$ \\
\hspace{+3mm}7.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min \ne max$ then do \\
\hspace{+3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{+6mm}8.1.1  $c_n \leftarrow x_n + u$ \\
\hspace{+6mm}8.1.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9.  $c_{max} \leftarrow u$ \\
10.  if $olduse > max$ then \\
\hspace{+3mm}10.1  for $n$ from $max + 1$ to $oldused - 1$ do \\
\hspace{+6mm}10.1.1  $c_n \leftarrow 0$ \\
11.  Clamp excess digits in $c$.  (\textit{mp\_clamp}) \\
12.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_add}
\end{figure}

\textbf{Algorithm s\_mp\_add.}
This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.  
Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}.  Even the 
MIX pseudo  machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.

The first thing that has to be accomplished is to sort out which of the two inputs is the largest.  The addition logic
will simply add all of the smallest input to the largest input and store that first part of the result in the
destination.  Then it will apply a simpler addition loop to excess digits of the larger input.

The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two 
inputs.  The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
same number of digits.  After the inputs are sorted the destination $c$ is grown as required to accomodate the sum 
of the two inputs.  The original \textbf{used} count of $c$ is copied and set to the new used count.  

At this point the first addition loop will go through as many digit positions that both inputs have.  The carry
variable $\mu$ is set to zero outside the loop.  Inside the loop an ``addition'' step requires three statements to produce
one digit of the summand.  First
two digits from $a$ and $b$ are added together along with the carry $\mu$.  The carry of this step is extracted and stored
in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.

Now all of the digit positions that both inputs have in common have been exhausted.  If $min \ne max$ then $x$ is an alias
for one of the inputs that has more digits.  A simplified addition loop is then used to essentially copy the remaining digits
and the carry to the destination.

The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.


\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

We first sort (lines 28 to 36) the inputs based on magnitude and determine the $min$ and $max$ variables.
Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias.  Next we
grow the destination (38 to 42) ensure that it can accomodate the result of the addition. 

Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style.  The three aliases that are on 
lines 56, 59 and 62 represent the two inputs and destination variables respectively.  These aliases are used to ensure the
compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.

The initial carry $u$ will be cleared (line 65), note that $u$ is of type mp\_digit which ensures type 
compatibility within the implementation.  The initial addition (line 66 to 75) adds digits from
both inputs until the smallest input runs out of digits.  Similarly the conditional addition loop
(line 81 to 90) adds the remaining digits from the larger of the two inputs.  The addition is finished 
with the final carry being stored in $tmpc$ (line 94).  Note the ``++'' operator within the same expression.
After line 94, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$.  This is useful
for the next loop (line 97 to 99) which set any old upper digits to zero.

\subsection{Low Level Subtraction}
The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm.  The principle difference is that the
unsigned subtraction algorithm requires the result to be positive.  That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must 
be met for this algorithm to function properly.  Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.  
This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.


For this algorithm a new variable is required to make the description simpler.  Recall from section 1.3.1 that a mp\_digit must be able to represent
the range $0 \le x < 2\beta$ for the algorithms to work correctly.  However, it is allowable that a mp\_digit represent a larger range of values.  For 
this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a 
mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).  

For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$.  In ISO C an ``unsigned long''
data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.

\newpage\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
\textbf{Output}.  The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
\hline \\
1.  $min \leftarrow b.used$ \\
2.  $max \leftarrow a.used$ \\
3.  If $c.alloc < max$ then grow $c$ to hold at least $max$ digits.  (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\ 
5.  $c.used \leftarrow max$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{3mm}7.1  $c_n \leftarrow a_n - b_n - u$ \\
\hspace{3mm}7.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min < max$ then do \\
\hspace{3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{6mm}8.1.1  $c_n \leftarrow a_n - u$ \\
\hspace{6mm}8.1.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9. if $oldused > max$ then do \\
\hspace{3mm}9.1  for $n$ from $max$ to $oldused - 1$ do \\
\hspace{6mm}9.1.1  $c_n \leftarrow 0$ \\
10. Clamp excess digits of $c$.  (\textit{mp\_clamp}). \\
11. Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_sub}
\end{figure}

\textbf{Algorithm s\_mp\_sub.}
This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive.  That is when
passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly.  This
algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well.  As was the case
of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.

The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$.  Steps 1 and 2 
set the $min$ and $max$ variables.  Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at 
most $max$ digits in length as opposed to $max + 1$.  Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and 
set to the maximal count for the operation.

The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision 
subtraction is used instead.  Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction 
loops.  Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.  

For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$.  The least significant bit will force a carry upwards to 
the third bit which will be set to zero after the borrow.  After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain,  When the 
third bit of $0101_2$ is subtracted from the result it will cause another carry.  In this case though the carry will be forced to propagate all the 
way to the most significant bit.  

Recall that $\beta < 2^{\gamma}$.  This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most 
significant bit.  Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
is needed is a single zero or one bit for the carry.  Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the 
carry.  This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.  

If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$.  Step
10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Like low level addition we ``sort'' the inputs.  Except in this case the sorting is hardcoded 
(lines 25 and 26).  In reality the $min$ and $max$ variables are only aliases and are only 
used to make the source code easier to read.  Again the pointer alias optimization is used 
within this algorithm.  The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
(lines 42, 43 and 44) for $a$, $b$ and $c$ respectively.

The first subtraction loop (lines 47 through 61) subtract digits from both inputs until the smaller of
the two inputs has been exhausted.  As remarked earlier there is an implementation reason for using the ``awkward'' 
method of extracting the carry (line 57).  The traditional method for extracting the carry would be to shift 
by $lg(\beta)$ positions and logically AND the least significant bit.  The AND operation is required because all of 
the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction.  This carry 
extraction requires two relatively cheap operations to extract the carry.  The other method is to simply shift the 
most significant bit to the least significant bit thus extracting the carry with a single cheap operation.  This 
optimization only works on twos compliment machines which is a safe assumption to make.

If $a$ has a larger magnitude than $b$ an additional loop (lines 64 through 73) is required to propagate 
the carry through $a$ and copy the result to $c$.  

\subsection{High Level Addition}
Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
established.  This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data 
types.  

Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} 
flag.  A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed addition $c = a + b$. \\
\hline \\
1.  if $a.sign = b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$  \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag})  \\
\hspace{6mm}2.1.1  $c.sign \leftarrow b.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert a \vert - \vert b \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_add}
\end{figure}

\textbf{Algorithm mp\_add.}
This algorithm performs the signed addition of two mp\_int variables.  There is no reference algorithm to draw upon from 
either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations.  The algorithm is fairly 
straightforward but restricted since subtraction can only produce positive results.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&&\\

\hline $+$ & $-$ & No  & $c = b - a$ & $b.sign$ \\
\hline $-$ & $+$ & No  & $c = b - a$ & $b.sign$ \\

\hline &&&&\\

\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\

\hline
\end{tabular}
\end{center}
\end{small}
\caption{Addition Guide Chart}
\label{fig:AddChart}
\end{figure}

Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three 
specific cases need to be handled.  The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are 
forwarded to step three to check for errors.  This simplifies the description of the algorithm considerably and best 
follows how the implementation actually was achieved.

Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed.  Recall from the descriptions of algorithms
s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits.  The mp\_clamp algorithm will set the \textbf{sign}
to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.

For example, consider performing $-a + a$ with algorithm mp\_add.  By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
produce a result of $-0$.  However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp 
within algorithm s\_mp\_add will force $-0$ to become $0$.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_add.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The source code follows the algorithm fairly closely.  The most notable new source code addition is the usage of the $res$ integer variable which
is used to pass result of the unsigned operations forward.  Unlike in the algorithm, the variable $res$ is merely returned as is without
explicitly checking it and returning the constant \textbf{MP\_OKAY}.  The observation is this algorithm will succeed or fail only if the lower
level functions do so.  Returning their return code is sufficient.

\subsection{High Level Subtraction}
The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.  

\newpage\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed subtraction $c = a - b$. \\
\hline \\
1.  if $a.sign \ne b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$ \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
\hspace{6mm}2.1.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert a \vert  - \vert b \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = MP\_NEG \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert b \vert  - \vert a \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_sub}
\end{figure}

\textbf{Algorithm mp\_sub.}
This algorithm performs the signed subtraction of two inputs.  Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or 
\cite{HAC}.  Also this algorithm is restricted by algorithm s\_mp\_sub.  Chart \ref{fig:SubChart} lists the eight possible inputs and
the operations required.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline $-$ & $-$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Subtraction Guide Chart}
\label{fig:SubChart}
\end{figure}

Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction.  That is to prevent the 
algorithm from producing $-a - -a = -0$ as a result.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
and forward it to the end of the function.  On line 39 the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a 
``greater than or equal to'' comparison.  

\section{Bit and Digit Shifting}
It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.  
This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.  

In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established.  That is to shift
the digits left or right as well to shift individual bits of the digits left and right.  It is important to note that not all ``shift'' operations
are on radix-$\beta$ digits.  

\subsection{Multiplication by Two}

In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient 
operation to perform.  A single precision logical shift left is sufficient to multiply a single digit by two.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = 2a$. \\
\hline \\
1.  If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits.  (\textit{mp\_grow}) \\
2.  $oldused \leftarrow b.used$ \\
3.  $b.used \leftarrow a.used$ \\
4.  $r \leftarrow 0$ \\
5.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}5.1  $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
\hspace{3mm}5.2  $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.3  $r \leftarrow rr$ \\
6.  If $r \ne 0$ then do \\
\hspace{3mm}6.1  $b_{n + 1} \leftarrow r$ \\
\hspace{3mm}6.2  $b.used \leftarrow b.used + 1$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2}
\end{figure}

\textbf{Algorithm mp\_mul\_2.}
This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two.  Neither \cite{TAOCPV2} nor \cite{HAC} describe such 
an algorithm despite the fact it arises often in other algorithms.  The algorithm is setup much like the lower level algorithm s\_mp\_add since 
it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.  

Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result.  The initial \textbf{used} count
is set to $a.used$ at step 4.  Only if there is a final carry will the \textbf{used} count require adjustment.

Step 6 is an optimization implementation of the addition loop for this specific case.  That is since the two values being added together 
are the same there is no need to perform two reads from the digits of $a$.  Step 6.1 performs a single precision shift on the current digit $a_n$ to
obtain what will be the carry for the next iteration.  Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
the previous carry.  Recall from section 4.1 that $a_n << 1$ is equivalent to $a_n \cdot 2$.  An iteration of the addition loop is finished with 
forwarding the carry to the next iteration.

Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.  
Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input.  The only noteworthy difference
is the use of the logical shift operator on line 52 to perform a single precision doubling.  

\subsection{Division by Two}
A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = a/2$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits.  (\textit{mp\_grow}) \\
2.  If the reallocation failed return(\textit{MP\_MEM}). \\
3.  $oldused \leftarrow b.used$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $r \leftarrow 0$ \\
6.  for $n$ from $b.used - 1$ to $0$ do \\
\hspace{3mm}6.1  $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
\hspace{3mm}6.2  $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}6.3  $r \leftarrow rr$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Clamp excess digits of $b$.  (\textit{mp\_clamp}) \\
10.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2}
\end{figure}

\textbf{Algorithm mp\_div\_2.}
This algorithm will divide an mp\_int by two using logical shifts to the right.  Like mp\_mul\_2 it uses a modified low level addition
core as the basis of the algorithm.  Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit.  The algorithm
could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
reading past the end of the array of digits.

Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the 
least significant bit not the most significant bit.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\section{Polynomial Basis Operations}
Recall from section 4.3 that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$.  Such a representation is also known as
the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single 
place.  The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
division and Karatsuba multiplication.  

Converting from an array of digits to polynomial basis is very simple.  Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
$y = \sum_{i=0}^{2} a_i \beta^i$.  Simply replace $\beta$ with $x$ and the expression is in polynomial basis.  For example, $f(x) = 8x + 9$ is the
polynomial basis representation for $89$ using radix ten.  That is, $f(10) = 8(10) + 9 = 89$.  

\subsection{Multiplication by $x$}

Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one 
degree.  In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$.  From a scalar basis point of view multiplying by $x$ is equivalent to
multiplying by the integer $\beta$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_OKAY}). \\
2.  If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits.  (\textit{mp\_grow}). \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  $a.used \leftarrow a.used + b$ \\
5.  $i \leftarrow a.used - 1$ \\
6.  $j \leftarrow a.used - 1 - b$ \\
7.  for $n$ from $a.used - 1$ to $b$ do \\
\hspace{3mm}7.1  $a_{i} \leftarrow a_{j}$ \\
\hspace{3mm}7.2  $i \leftarrow i - 1$ \\
\hspace{3mm}7.3  $j \leftarrow j - 1$ \\
8.  for $n$ from 0 to $b - 1$ do \\
\hspace{3mm}8.1  $a_n \leftarrow 0$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lshd}
\end{figure}

\textbf{Algorithm mp\_lshd.}
This algorithm multiplies an mp\_int by the $b$'th power of $x$.  This is equivalent to multiplying by $\beta^b$.  The algorithm differs 
from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location.  The
motivation behind this change is due to the way this function is typically used.  Algorithms such as mp\_add store the result in an optionally
different third mp\_int because the original inputs are often still required.  Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
typically used on values where the original value is no longer required.  The algorithm will return success immediately if 
$b \le 0$ since the rest of algorithm is only valid when $b > 0$.  

First the destination $a$ is grown as required to accomodate the result.  The counters $i$ and $j$ are used to form a \textit{sliding window} over
the digits of $a$ of length $b$.  The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).  
The loop on step 7 copies the digit from the tail to the head.  In each iteration the window is moved down one digit.   The last loop on 
step 8 sets the lower $b$ digits to zero.

\newpage
\begin{center}
\begin{figure}[here]
\includegraphics{pics/sliding_window.ps}
\caption{Sliding Window Movement}
\label{pic:sliding_window}
\end{figure}
\end{center}

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The if statement (line 24) ensures that the $b$ variable is greater than zero since we do not interpret negative
shift counts properly.  The \textbf{used} count is incremented by $b$ before the copy loop begins.  This elminates 
the need for an additional variable in the for loop.  The variable $top$ (line 42) is an alias
for the leading digit while $bottom$ (line 45) is an alias for the trailing edge.  The aliases form a 
window of exactly $b$ digits over the input.  

\subsection{Division by $x$}

Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return. \\
2.  If $a.used \le b$ then do \\
\hspace{3mm}2.1  Zero $a$.  (\textit{mp\_zero}). \\
\hspace{3mm}2.2  Return. \\
3.  $i \leftarrow 0$ \\
4.  $j \leftarrow b$ \\
5.  for $n$ from 0 to $a.used - b - 1$ do \\
\hspace{3mm}5.1  $a_i \leftarrow a_j$ \\
\hspace{3mm}5.2  $i \leftarrow i + 1$ \\
\hspace{3mm}5.3  $j \leftarrow j + 1$ \\
6.  for $n$ from $a.used - b$ to $a.used - 1$ do \\
\hspace{3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.used \leftarrow a.used - b$ \\
8.  Return. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rshd}
\end{figure}

\textbf{Algorithm mp\_rshd.}
This algorithm divides the input in place by the $b$'th power of $x$.  It is analogous to dividing by a $\beta^b$ but much quicker since
it does not require single precision division.  This algorithm does not actually return an error code as it cannot fail.  

If the input $b$ is less than one the algorithm quickly returns without performing any work.  If the \textbf{used} count is less than or equal
to the shift count $b$ then it will simply zero the input and return.

After the trivial cases of inputs have been handled the sliding window is setup.  Much like the case of algorithm mp\_lshd a sliding window that
is $b$ digits wide is used to copy the digits.  Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.  
Also the digits are copied from the leading to the trailing edge.

Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The only noteworthy element of this routine is the lack of a return type since it cannot fail.  Like mp\_lshd() we
form a sliding window except we copy in the other direction.  After the window (line 60) we then zero
the upper digits of the input to make sure the result is correct.

\section{Powers of Two}

Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required.  For 
example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful.  Instead of performing single
shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.  

\subsection{Multiplication by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot 2^b$. \\
\hline \\
1.  $c \leftarrow a$.  (\textit{mp\_copy}) \\
2.  If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  If $b \ge lg(\beta)$ then \\
\hspace{3mm}4.1  $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
\hspace{3mm}4.2  If step 4.1 failed return(\textit{MP\_MEM}). \\
5.  $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $d \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^d$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $0$ to $c.used - 1$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
\hspace{3mm}6.4  If $r > 0$ then do \\
\hspace{6mm}6.4.1  $c_{c.used} \leftarrow r$ \\
\hspace{6mm}6.4.2  $c.used \leftarrow c.used + 1$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2d}
\end{figure}

\textbf{Algorithm mp\_mul\_2d.}
This algorithm multiplies $a$ by $2^b$ and stores the result in $c$.  The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
quickly compute the product.

First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than 
$\beta$.  For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ 
left.

After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform.  Step 5 calculates the number of remaining shifts 
required.  If it is non-zero a modified shift loop is used to calculate the remaining product.  
Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$.  The $mask$
variable is used to extract the upper $d$ bits to form the carry for the next iteration.  

This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to 
complete.  It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The shifting is performed in--place which means the first step (line 25) is to copy the input to the 
destination.  We avoid calling mp\_copy() by making sure the mp\_ints are different.  The destination then
has to be grown (line 32) to accomodate the result.

If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples 
of $lg(\beta)$.  Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left.  Inside the actual shift 
loop (lines 46 to 76) we make use of pre--computed values $shift$ and $mask$.   These are used to
extract the carry bit(s) to pass into the next iteration of the loop.  The $r$ and $rr$ variables form a 
chain between consecutive iterations to propagate the carry.  

\subsection{Division by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}1.2  $d \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.3  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow a$ \\
3.  $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
4.  If $b \ge lg(\beta)$ then do \\
\hspace{3mm}4.1  $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
5.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $k \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^k$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $c.used - 1$ to $0$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
7.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2d}
\end{figure}

\textbf{Algorithm mp\_div\_2d.}
This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder.  The algorithm is designed much like algorithm 
mp\_mul\_2d by first using whole digit shifts then single precision shifts.  This algorithm will also produce the remainder of the division
by using algorithm mp\_mod\_2d.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies.  The remainder $d$ may be optionally 
ignored by passing \textbf{NULL} as the pointer to the mp\_int variable.    The temporary mp\_int variable $t$ is used to hold the 
result of the remainder operation until the end.  This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
the quotient is obtained.

The remainder of the source code is essentially the same as the source code for mp\_mul\_2d.  The only significant difference is
the direction of the shifts.

\subsection{Remainder of Division by Power of Two}

The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$.  This
algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mod\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $b > a.used \cdot lg(\beta)$ then do \\
\hspace{3mm}2.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}2.2  Return the result of step 2.1. \\
3.  $c \leftarrow a$ \\
4.  If step 3 failed return(\textit{MP\_MEM}). \\
5.  for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
\hspace{3mm}5.1  $c_n \leftarrow 0$ \\
6.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
7.  $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
8.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mod\_2d}
\end{figure}

\textbf{Algorithm mp\_mod\_2d.}
This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$.  First if $b$ is less than or equal to zero the 
result is set to zero.  If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns.  Otherwise, $a$ 
is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases.  Next if $2^b$ is larger
than the input we just mp\_copy() the input and return right away.  After this point we know we must actually
perform some work to produce the remainder.

Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce 
the number.  First we zero any digits above the last digit in $2^b$ (line 42).  Next we reduce the 
leading digit of both (line 46) and then mp\_clamp().

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
                      & in $O(n)$ time. \\
                      &\\
$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming  \\
                      & weight values such as $3$, $5$ and $9$.  Extend it to handle all values \\
                      & upto $64$ with a hamming weight less than three. \\
                      &\\
$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
                      & $2^k - 1$ as well. \\
                      &\\
$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
                      & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
                      & any $n$-bit input.  Note that the time of addition is ignored in the \\
                      & calculation.  \\
                      & \\
$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
                      & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$.  Again ignore \\
                      & the cost of addition. \\
                      & \\
$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
                      & for $n = 64 \ldots 1024$ in steps of $64$. \\
                      & \\
$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
                      & calculating the result of a signed comparison. \\
                      &
\end{tabular}

\chapter{Multiplication and Squaring}
\section{The Multipliers}
For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of 
algorithms of any multiple precision integer package.  The set of multiplier algorithms include integer multiplication, squaring and modular reduction 
where in each of the algorithms single precision multiplication is the dominant operation performed.  This chapter will discuss integer multiplication 
and squaring, leaving modular reductions for the subsequent chapter.  

The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular 
exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$.  During a modular
exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, 
35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision 
multiplications.

For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied 
against every digit of the other multiplicand.  Traditional long-hand multiplication is based on this process;  while the techniques can differ the 
overall algorithm used is essentially the same.  Only ``recently'' have faster algorithms been studied.  First Karatsuba multiplication was discovered in 
1962.  This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.  
This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.  

\section{Multiplication}
\subsection{The Baseline Multiplication}
\label{sec:basemult}
\index{baseline multiplication}
Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
algorithm that school children are taught.  The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision 
multiplications are required.  More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required.  To 
simplify most discussions, it will be assumed that the inputs have comparable number of digits.  

The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be 
used.  This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible.    One important 
facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution.  The importance of this 
modification will become evident during the discussion of Barrett modular reduction.  Recall that for a $n$ and $m$ digit input the product 
will be at most $n + m$ digits.  Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.  

Recall from sub-section 4.2.2 the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}.  We shall now extend the variable set to 
include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}.  This implies that $2^{\alpha} > 2 \cdot \beta^2$.  The 
constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see sub-section 5.2.2 for more information}).

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
1.  If min$(a.used, b.used) < \delta$ then do \\
\hspace{3mm}1.1  Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}).  \\
\hspace{3mm}1.2  Return the result of step 1.1 \\
\\
Allocate and initialize a temporary mp\_int. \\
2.  Init $t$ to be of size $digs$ \\
3.  If step 2 failed return(\textit{MP\_MEM}). \\
4.  $t.used \leftarrow digs$ \\
\\
Compute the product. \\
5.  for $ix$ from $0$ to $a.used - 1$ do \\
\hspace{3mm}5.1  $u \leftarrow 0$ \\
\hspace{3mm}5.2  $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
\hspace{3mm}5.3  If $pb < 1$ then goto step 6. \\
\hspace{3mm}5.4  for $iy$ from $0$ to $pb - 1$ do \\
\hspace{6mm}5.4.1  $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
\hspace{6mm}5.4.2  $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.5  if $ix + pb < digs$ then do \\
\hspace{6mm}5.5.1  $t_{ix + pb} \leftarrow u$ \\
6.  Clamp excess digits of $t$. \\
7.  Swap $c$ with $t$ \\
8.  Clear $t$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_mul\_digs}
\end{figure}

\textbf{Algorithm s\_mp\_mul\_digs.}
This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits.  While it may seem
a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent 
algorithm.  The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.  
Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the 
inputs.

The first thing this algorithm checks for is whether a Comba multiplier can be used instead.   If the minimum digit count of either
input is less than $\delta$, then the Comba method may be used instead.    After the Comba method is ruled out, the baseline algorithm begins.  A 
temporary mp\_int variable $t$ is used to hold the intermediate result of the product.  This allows the algorithm to be used to 
compute products when either $a = c$ or $b = c$ without overwriting the inputs.  

All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output.  The $pb$ variable
is given the count of digits to read from $b$ inside the nested loop.  If $pb \le 1$ then no more output digits can be produced and the algorithm
will exit the loop.  The best way to think of the loops are as a series of $pb \times 1$ multiplications.    That is, in each pass of the 
innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.  

For example, consider multiplying $576$ by $241$.  That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
visualized in the following table.

\begin{figure}[here]
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|l|}
\hline   &&          & 5 & 7 & 6 & \\
\hline   $\times$&&  & 2 & 4 & 1 & \\
\hline &&&&&&\\
  &&          & 5 & 7 & 6 & $10^0(1)(576)$ \\
  &2 &   3    & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
  1 & 3 & 8 & 8 & 1 & 6 &   $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
\hline  
\end{tabular}
\end{center}
\caption{Long-Hand Multiplication Diagram}
\end{figure}

Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate 
count.  That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.

Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable.  The multiplication on that step
is assumed to be a double wide output single precision multiplication.  That is, two single precision variables are multiplied to produce a
double precision result.  The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
5.4.1 is propagated through the nested loop.  If the carry was not propagated immediately it would overflow the single precision digit 
$t_{ix+iy}$ and the result would be lost.  

At step 5.5 the nested loop is finished and any carry that was left over should be forwarded.  The carry does not have to be added to the $ix+pb$'th
digit since that digit is assumed to be zero at this point.  However, if $ix + pb \ge digs$ the carry is not set as it would make the result
exceed the precision requested.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

First we determine (line 31) if the Comba method can be used first since it's faster.  The conditions for 
sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than 
\textbf{MP\_WARRAY}.  This new constant is used to control the stack usage in the Comba routines.  By default it is 
set to $\delta$ but can be reduced when memory is at a premium.

If we cannot use the Comba method we proceed to setup the baseline routine.  We allocate the the destination mp\_int
$t$ (line 37) to the exact size of the output to avoid further re--allocations.  At this point we now 
begin the $O(n^2)$ loop.

This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
digits as output.  In each iteration of the outer loop the $pb$ variable is set (line 49) to the maximum 
number of inner loop iterations.  

Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
carry from the previous iteration.  A particularly important observation is that most modern optimizing 
C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that 
is required for the product.  In x86 terms for example, this means using the MUL instruction.

Each digit of the product is stored in turn (line 69) and the carry propagated (line 72) to the 
next iteration.

\subsection{Faster Multiplication by the ``Comba'' Method}

One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be 
computed and propagated upwards.  This makes the nested loop very sequential and hard to unroll and implement 
in parallel.  The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. 
Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations.  As an 
interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written 
five years before.

At the heart of the Comba technique is once again the long-hand algorithm.  Except in this case a slight 
twist is placed on how the columns of the result are produced.  In the standard long-hand algorithm rows of products 
are produced then added together to form the final result.  In the baseline algorithm the columns are added together 
after each iteration to get the result instantaneously.  

In the Comba algorithm the columns of the result are produced entirely independently of each other.  That is at 
the $O(n^2)$ level a simple multiplication and addition step is performed.  The carries of the columns are propagated 
after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute 
the product vector $\vec x$ as follows. 

\begin{equation}
\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
\end{equation}

Where $\vec x_n$ is the $n'th$ column of the output vector.  Consider the following example which computes the vector $\vec x$ for the multiplication
of $576$ and $241$.  

\newpage\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|}
  \hline &          & 5 & 7 & 6 & First Input\\
  \hline $\times$ & & 2 & 4 & 1 & Second Input\\
\hline            &                        & $1 \cdot 5 = 5$   & $1 \cdot 7 = 7$   & $1 \cdot 6 = 6$ & First pass \\
                  &  $4 \cdot 5 = 20$      & $4 \cdot 7+5=33$  & $4 \cdot 6+7=31$  & 6               & Second pass \\
   $2 \cdot 5 = 10$ &  $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31                & 6             & Third pass \\
\hline 10 & 34 & 45 & 31 & 6 & Final Result \\   
\hline   
\end{tabular}
\end{center}
\end{small}
\caption{Comba Multiplication Diagram}
\end{figure}

At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.  
Now the columns must be fixed by propagating the carry upwards.  The resultant vector will have one extra dimension over the input vector which is
congruent to adding a leading zero digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Comba Fixup}. \\
\textbf{Input}.   Vector $\vec x$ of dimension $k$ \\
\textbf{Output}.  Vector $\vec x$ such that the carries have been propagated. \\
\hline \\
1.  for $n$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
2.  Return($\vec x$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Comba Fixup}
\end{figure}

With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$.  In this case 
$241 \cdot 576$ is in fact $138816$ and the procedure succeeded.  If the algorithm is correct and as will be demonstrated shortly more
efficient than the baseline algorithm why not simply always use this algorithm?

\subsubsection{Column Weight.}
At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output 
independently.  A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
the carries.  For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
three single precision multiplications.  If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
an overflow can occur and the carry information will be lost.  For any $m$ and $n$ digit inputs the maximum weight of any column is 
min$(m, n)$ which is fairly obvious.

The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used.  Recall
from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision.  Given these
two quantities we must not violate the following

\begin{equation}
k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
\end{equation}

Which reduces to 

\begin{equation}
k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
\end{equation}

Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit.  By further re-arrangement of the equation the final solution is
found.

\begin{equation}
k  < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
\end{equation}

The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$.  In this configuration 
the smaller input may not have more than $256$ digits if the Comba method is to be used.  This is quite satisfactory for most applications since 
$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
1.  If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
2.  If step 1 failed return(\textit{MP\_MEM}).\\
\\
3.  $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
\\
4.  $\_ \hat W \leftarrow 0$ \\
5.  for $ix$ from 0 to $pa - 1$ do \\
\hspace{3mm}5.1  $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
\hspace{3mm}5.2  $tx \leftarrow ix - ty$ \\
\hspace{3mm}5.3  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
\hspace{3mm}5.4  for $iz$ from 0 to $iy - 1$ do \\
\hspace{6mm}5.4.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
\hspace{3mm}5.5  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
\hspace{3mm}5.6  $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
\\
6.  $oldused \leftarrow c.used$ \\
7.  $c.used \leftarrow digs$ \\
8.  for $ix$ from $0$ to $pa$ do \\
\hspace{3mm}8.1  $c_{ix} \leftarrow W_{ix}$ \\
9.  for $ix$ from $pa + 1$ to $oldused - 1$ do \\
\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
\\
10.  Clamp $c$. \\
11.  Return MP\_OKAY. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_mul\_digs}
\label{fig:COMBAMULT}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_mul\_digs.}
This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.

The outer loop of this algorithm is more complicated than that of the baseline multiplier.  This is because on the inside of the 
loop we want to produce one column per pass.  This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.

The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$.  That way if $a$ has more digits than
$b$ this will be limited to $b.used - 1$.  The $tx$ variable is set to the to the distance past $b.used$ the variable
$ix$ is.  This is used for the immediately subsequent statement where we find $iy$.  

The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out.  Computing one column at a time
means we have to scan one integer upwards and the other downwards.  $a$ starts at $tx$ and $b$ starts at $ty$.  In each
pass we are producing the $ix$'th output column and we note that $tx + ty = ix$.  As we move $tx$ upwards we have to 
move $ty$ downards so the equality remains valid.  The $iy$ variable is the number of iterations until 
$tx \ge a.used$ or $ty < 0$ occurs.

After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
into the next round by dividing $\_ \hat W$ by $\beta$.

To measure the benefits of the Comba method over the baseline method consider the number of operations that are required.  If the 
cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require 
$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers.  The Comba method requires only $O(pn^2 + qn)$ time, however in practice, 
the speed increase is actually much more.  With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
and addition operations in the nested loop in parallel.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

As per the pseudo--code we first calculate $pa$ (line 48) as the number of digits to output.  Next we begin the outer loop
to produce the individual columns of the product.  We use the two aliases $tmpx$ and $tmpy$ (lines 62, 63) to point
inside the two multiplicands quickly.  

The inner loop (lines 71 to 74) of this implementation is where the tradeoff come into play.  Originally this comba 
implementation was ``row--major'' which means it adds to each of the columns in each pass.  After the outer loop it would then fix 
the carries.  This was very fast except it had an annoying drawback.  You had to read a mp\_word and two mp\_digits and write 
one mp\_word per iteration.  On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth 
is very high and it can keep the ALU fed with data.  It did, however, matter on older and embedded cpus where cache is often 
slower and also often doesn't exist.  This new algorithm only performs two reads per iteration under the assumption that the 
compiler has aliased $\_ \hat W$ to a CPU register.

After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 77, 80) to forward it as 
a carry for the next pass.  After the outer loop we use the final carry (line 77) as the last digit of the product.  

\subsection{Polynomial Basis Multiplication}
To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication.  In the following algorithms
the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and  
$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required.  In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
 
The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$.  The coefficients $w_i$ will
directly yield the desired product when $\beta$ is substituted for $x$.  The direct solution to solve for the $2n + 1$ coefficients
requires $O(n^2)$ time and would in practice be slower than the Comba technique.

However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown 
coefficients.   This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with 
Gaussian elimination.  This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in 
effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.  

The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible.  However, since 
$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place.  The benefit of this technique stems from the 
fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively.  As a result finding the $2n + 1$ relations required 
by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.

When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$.  The $\zeta_0$ term
is simply the product $W(0) = w_0 = a_0 \cdot b_0$.  The $\zeta_1$ term is the product 
$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$.  The third point $\zeta_{\infty}$ is less obvious but rather
simple to explain.  The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.  
The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$.  Note that the 
points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.

If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ for small values of $q$.  The term ``mirror point'' stems from the fact that 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$.  For
example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.

\begin{eqnarray}
\zeta_{2}                  = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
\end{eqnarray}

Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts.  For example, when $n = 2$ the
polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$.  This technique of polynomial representation is known as Horner's method.  

As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications.  Each multiplication is of 
multiplicands that have $n$ times fewer digits than the inputs.  The asymptotic running time of this algorithm is 
$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}).  Figure~\ref{fig:exponent}
summarizes the exponents for various values of $n$.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Split into $n$ Parts} & \textbf{Exponent}  & \textbf{Notes}\\
\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
\hline $4$ & $1.403677461$ &\\
\hline $5$ & $1.365212389$ &\\
\hline $10$ & $1.278753601$ &\\
\hline $100$ & $1.149426538$ &\\
\hline $1000$ & $1.100270931$ &\\
\hline $10000$ & $1.075252070$ &\\
\hline
\end{tabular}
\end{center}
\caption{Asymptotic Running Time of Polynomial Basis Multiplication}
\label{fig:exponent}
\end{figure}

At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$.  However, the overhead
of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
numbers.  

\subsubsection{Cutoff Point}
The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach.  However, 
the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved.  This makes the
polynomial basis approach more costly to use with small inputs.

Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}).  There exists a 
point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and 
when $m > y$ the Comba methods are slower than the polynomial basis algorithms.  

The exact location of $y$ depends on several key architectural elements of the computer platform in question.

\begin{enumerate}
\item  The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc.  For example
on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$.  The higher the ratio in favour of multiplication the lower
the cutoff point $y$ will be.  

\item  The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is.  Generally speaking as the number of splits
grows the complexity grows substantially.  Ideally solving the system will only involve addition, subtraction and shifting of integers.  This
directly reflects on the ratio previous mentioned.

\item  To a lesser extent memory bandwidth and function call overheads.  Provided the values are in the processor cache this is less of an
influence over the cutoff point.

\end{enumerate}

A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met.  For example, if the point
is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster.  Finding the cutoff points is fairly simple when
a high resolution timer is available.  

\subsection{Karatsuba Multiplication}
Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
general purpose multiplication.  Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with 
light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.

\begin{equation}
f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd
\end{equation}

Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product.  Applying
this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique.  It turns 
out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points 
$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$.  Consider the resultant system of equations.

\begin{center}
\begin{tabular}{rcrcrcrc}
$\zeta_{0}$ &      $=$ &  &  &  & & $w_0$ \\
$\zeta_{1}$ &      $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\
$\zeta_{\infty}$ & $=$ & $w_2$ &  & &  & \\
\end{tabular}
\end{center}

By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for.  The simplicity
of this system of equations has made Karatsuba fairly popular.  In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
\hline \\
1.  Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
2.  If step 2 failed then return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1 \cdot \beta^B + x0$ \\
3.  $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
6.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
7.  $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
\\
Calculate the three products. \\
8.  $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
9.  $x1y1 \leftarrow x1 \cdot y1$ \\
10.  $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\
11.  $x0 \leftarrow y1 + y0$ \\
12.  $t1 \leftarrow t1 \cdot x0$ \\
\\
Calculate the middle term. \\
13.  $x0 \leftarrow x0y0 + x1y1$ \\
14.  $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\
\\
Calculate the final product. \\
15.  $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
16.  $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
17.  $t1 \leftarrow x0y0 + t1$ \\
18.  $c \leftarrow t1 + x1y1$ \\
19.  Clear all of the temporary variables. \\
20.  Return(\textit{MP\_OKAY}).\\
\hline 
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_mul}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_mul.}
This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm.  It is loosely based on the description
from Knuth \cite[pp. 294-295]{TAOCPV2}.  

\index{radix point}
In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen.  The radix point chosen must
be used for both of the inputs meaning that it must be smaller than the smallest input.  Step 3 chooses the radix point $B$ as half of the 
smallest input \textbf{used} count.  After the radix point is chosen the inputs are split into lower and upper halves.  Step 4 and 5 
compute the lower halves.  Step 6 and 7 computer the upper halves.  

After the halves have been computed the three intermediate half-size products must be computed.  Step 8 and 9 compute the trivial products
$x0 \cdot y0$ and $x1 \cdot y1$.  The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed.  By using $x0$ instead
of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.

The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The new coding element in this routine, not  seen in previous routines, is the usage of goto statements.  The conventional
wisdom is that goto statements should be avoided.  This is generally true, however when every single function call can fail, it makes sense
to handle error recovery with a single piece of code.  Lines 62 to 76 handle initializing all of the temporary variables 
required.  Note how each of the if statements goes to a different label in case of failure.  This allows the routine to correctly free only
the temporaries that have been successfully allocated so far.

The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large.  This saves the 
additional reallocation that would have been necessary.  Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
number of digits for the next section of code.

The first algebraic portion of the algorithm is to split the two inputs into their halves.  However, instead of using mp\_mod\_2d and mp\_rshd
to extract the halves, the respective code has been placed inline within the body of the function.  To initialize the halves, the \textbf{used} and 
\textbf{sign} members are copied first.  The first for loop on line 96 copies the lower halves.  Since they are both the same magnitude it 
is simpler to calculate both lower halves in a single loop.  The for loop on lines 102 and 107 calculate the upper halves $x1$ and 
$y1$ respectively.

By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.

When line 151 is reached, the algorithm has completed succesfully.  The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
the same code that handles errors can be used to clear the temporary variables and return.  

\subsection{Toom-Cook $3$-Way Multiplication}
Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points  are 
chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce.  Here, the points $\zeta_{0}$, 
$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients 
of the $W(x)$.

With the five relations that Toom-Cook specifies, the following system of equations is formed.

\begin{center}
\begin{tabular}{rcrcrcrcrcr}
$\zeta_0$                    & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$  \\
$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$  \\
$\zeta_1$                    & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$  \\
$\zeta_2$                    & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$  \\
$\zeta_{\infty}$             & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$  \\
\end{tabular}
\end{center}

A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
of two, two divisions by three and one multiplication by three.  All of these $19$ sub-operations require less than quadratic time, meaning that
the algorithm can be faster than a baseline multiplication.  However, the greater complexity of this algorithm places the cutoff point
(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow  a  \cdot  b $ \\
\hline \\
Split $a$ and $b$ into three pieces.  E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
1.  $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
2.  $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
3.  $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
4.  $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
5.  $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
6.  $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
7.  $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
\\
Find the five equations for $w_0, w_1, ..., w_4$. \\
8.  $w_0 \leftarrow a_0 \cdot b_0$ \\
9.  $w_4 \leftarrow a_2 \cdot b_2$ \\
10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
\\
Continued on the next page.\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot  b $ \\
\hline \\
Now solve the system of equations. \\
18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
\\
Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
26. for $n$ from $1$ to $4$ do \\
\hspace{3mm}26.1  $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
28. Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul (continued)}
\end{figure}

\textbf{Algorithm mp\_toom\_mul.}
This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach.  Compared to the Karatsuba multiplication, this 
algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead.  In this
description, several statements have been compounded to save space.  The intention is that the statements are executed from left to right across
any given step.

The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively.  From these smaller
integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.

The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively.  The relation $w_1, w_2$ and $w_3$ correspond
to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively.  These are found using logical shifts to independently find
$f(y)$ and $g(y)$ which significantly speeds up the algorithm.

After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients 
$w_1, w_2$ and $w_3$ to be isolated.  The steps 18 through 25 perform the system reduction required as previously described.  Each step of
the reduction represents the comparable matrix operation that would be performed had this been performed by pencil.  For example, step 18 indicates
that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.  

Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known.  By substituting $\beta^{k}$ for $x$, the integer 
result $a \cdot b$ is produced.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The first obvious thing to note is that this algorithm is complicated.  The complexity is worth it if you are multiplying very 
large numbers.  For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$).  For most ``crypto'' sized numbers this
algorithm is not practical as Karatsuba has a much lower cutoff point.

First we split $a$ and $b$ into three roughly equal portions.  This has been accomplished (lines 41 to 70) with 
combinations of mp\_rshd() and mp\_mod\_2d() function calls.  At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
for $b$.  

Next we compute the five points $w0, w1, w2, w3$ and $w4$.  Recall that $w0$ and $w4$ can be computed directly from the portions so
we get those out of the way first (lines 73 and 78).  Next we compute $w1, w2$ and $w3$ using Horners method.

After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
straight forward.  

\subsection{Signed Multiplication}
Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required.  So far all
of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot b$ \\
\hline \\
1.  If $a.sign = b.sign$ then \\
\hspace{3mm}1.1  $sign = MP\_ZPOS$ \\
2.  else \\
\hspace{3mm}2.1  $sign = MP\_ZNEG$ \\
3.  If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then  \\
\hspace{3mm}3.1  $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
4.  else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
\hspace{3mm}4.1  $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
5.  else \\
\hspace{3mm}5.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}5.2  If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
\hspace{6mm}5.2.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs.  \\
\hspace{3mm}5.3  else \\
\hspace{6mm}5.3.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs.  \\
6.  $c.sign \leftarrow sign$ \\
7.  Return the result of the unsigned multiplication performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul}
\end{figure}

\textbf{Algorithm mp\_mul.}
This algorithm performs the signed multiplication of two inputs.  It will make use of any of the three unsigned multiplication algorithms 
available when the input is of appropriate size.  The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
s\_mp\_mul\_digs will clear it.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The implementation is rather simplistic and is not particularly noteworthy.  Line 22 computes the sign of the result using the ``?'' 
operator from the C programming language.  Line 48 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.  

\section{Squaring}
\label{sec:basesquare}

Squaring is a special case of multiplication where both multiplicands are equal.  At first it may seem like there is no significant optimization
available but in fact there is.  Consider the multiplication of $576$ against $241$.  In total there will be nine single precision multiplications
performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot  6$, $2 \cdot 7$ and $2 \cdot 5$.  Now consider 
the multiplication of $123$ against $123$.  The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, 
$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$.  On closer inspection some of the products are equivalent.  For example, $3 \cdot 2 = 2 \cdot 3$ 
and $3 \cdot 1 = 1 \cdot 3$. 

For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
required for multiplication.  The following diagram gives an example of the operations required.

\begin{figure}[here]
\begin{center}
\begin{tabular}{ccccc|c}
&&1&2&3&\\
$\times$ &&1&2&3&\\
\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
       & $2 \cdot 1$  & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
         $1 \cdot 1$  & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
\end{tabular}
\end{center}
\caption{Squaring Optimization Diagram}
\end{figure}

Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious.  For the purposes of this discussion let $x$
represent the number being squared.  The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.  

The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product.  Every non-square term of a column will
appear twice hence the name ``double product''.  Every odd column is made up entirely of double products.  In fact every column is made up of double 
products and at most one square (\textit{see the exercise section}).  

The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, 
occurs at column $2k + 1$.  For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. 
Column two of row one is a square and column three is the first unique column.

\subsection{The Baseline Squaring Algorithm}
The baseline squaring algorithm is meant to be a catch-all squaring algorithm.  It will handle any of the input sizes that the faster routines
will not handle.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits.  (\textit{mp\_init\_size}) \\
2.  If step 1 failed return(\textit{MP\_MEM}) \\
3.  $t.used \leftarrow 2 \cdot a.used + 1$ \\
4.  For $ix$ from 0 to $a.used - 1$ do \\
\hspace{3mm}Calculate the square. \\
\hspace{3mm}4.1  $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
\hspace{3mm}4.2  $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}Calculate the double products after the square. \\
\hspace{3mm}4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}4.4  For $iy$ from $ix + 1$ to $a.used - 1$ do \\
\hspace{6mm}4.4.1  $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
\hspace{6mm}4.4.2  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}Set the last carry. \\
\hspace{3mm}4.5  While $u > 0$ do \\
\hspace{6mm}4.5.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}4.5.2  $\hat r \leftarrow t_{ix + iy} + u$ \\
\hspace{6mm}4.5.3  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.5.4  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  Clamp excess digits of $t$.  (\textit{mp\_clamp}) \\
6.  Exchange $b$ and $t$. \\
7.  Clear $t$ (\textit{mp\_clear}) \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_sqr}
\end{figure}

\textbf{Algorithm s\_mp\_sqr.}
This algorithm computes the square of an input using the three observations on squaring.  It is based fairly faithfully on  algorithm 14.16 of HAC
\cite[pp.596-597]{HAC}.  Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring.  This allows the 
destination mp\_int to be the same as the source mp\_int.

The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
the inner loop computes the columns of the partial result.  Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
the carry and compute the double products.  

The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
very algorithm.  The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
when it is multiplied by two, it can be properly represented by a mp\_word.

Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial 
results calculated so far.  This involves expensive carry propagation which will be eliminated in the next algorithm.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Inside the outer loop (line 34) the square term is calculated on line 37.  The carry (line 44) has been
extracted from the mp\_word accumulator using a right shift.  Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized 
(lines 47 and 50) to simplify the inner loop.  The doubling is performed using two
additions (line 59) since it is usually faster than shifting, if not at least as fast.  

The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication.  As such the inner loops
get progressively shorter as the algorithm proceeds.  This is what leads to the savings compared to using a multiplication to
square a number. 

\subsection{Faster Squaring by the ``Comba'' Method}
A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop.  Squaring has an additional
drawback that it must double the product inside the inner loop as well.  As for multiplication, the Comba technique can be used to eliminate these
performance hazards.

The first obvious solution is to make an array of mp\_words which will hold all of the columns.  This will indeed eliminate all of the carry
propagation operations from the inner loop.  However, the inner product must still be doubled $O(n^2)$ times.  The solution stems from the simple fact
that $2a + 2b + 2c = 2(a + b + c)$.  That is the sum of all of the double products is equal to double the sum of all the products.  For example,
$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.  

However, we cannot simply double all of the columns, since the squares appear only once per row.  The most practical solution is to have two 
mp\_word arrays.  One array will hold the squares and the other array will hold the double products.  With both arrays the doubling and 
carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level.  In this case, we have an even simpler solution in mind.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
1.  If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits.  (\textit{mp\_grow}). \\
2.  If step 1 failed return(\textit{MP\_MEM}). \\
\\
3.  $pa \leftarrow 2 \cdot a.used$ \\
4.  $\hat W1 \leftarrow 0$ \\
5.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}5.1  $\_ \hat W \leftarrow 0$ \\
\hspace{3mm}5.2  $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
\hspace{3mm}5.3  $tx \leftarrow ix - ty$ \\
\hspace{3mm}5.4  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
\hspace{3mm}5.5  $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
\hspace{3mm}5.6  for $iz$ from $0$ to $iz - 1$ do \\
\hspace{6mm}5.6.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
\hspace{3mm}5.7  $\_ \hat W \leftarrow 2 \cdot \_ \hat W  + \hat W1$ \\
\hspace{3mm}5.8  if $ix$ is even then \\
\hspace{6mm}5.8.1  $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
\hspace{3mm}5.9  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
\hspace{3mm}5.10  $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
\\
6.  $oldused \leftarrow b.used$ \\
7.  $b.used \leftarrow 2 \cdot a.used$ \\
8.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}8.1  $b_{ix} \leftarrow W_{ix}$ \\
9.  for $ix$ from $pa$ to $oldused - 1$ do \\
\hspace{3mm}9.1  $b_{ix} \leftarrow 0$ \\
10.  Clamp excess digits from $b$.  (\textit{mp\_clamp}) \\
11.  Return(\textit{MP\_OKAY}). \\ 
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_sqr}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_sqr.}
This algorithm computes the square of an input using the Comba technique.  It is designed to be a replacement for algorithm 
s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.  
This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.

First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively.  This is because the inner loop
products are to be doubled.  If we had added the previous carry in we would be doubling too much.  Next we perform an
addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits.  For example, $a_3 \cdot a_5$ is equal
$a_5 \cdot a_3$.  Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum
of the products just outside the inner loop we have to avoid doing this.  This is also a good thing since we perform
fewer multiplications and the routine ends up being faster.

Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8).  We add in the square
only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for 
the special case of squaring.  

\subsection{Polynomial Basis Squaring}
The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring.  The minor exception
is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$.  Instead of performing $2n + 1$
multiplications to find the $\zeta$ relations, squaring operations are performed instead.  

\subsection{Karatsuba Squaring}
Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.  
Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial.  The Karatsuba equation can be modified to square a 
number with the following equation.

\begin{equation}
h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2
\end{equation}

Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$.  As in 
Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of 
$O \left ( n^{lg(3)} \right )$.

If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm 
instead?  The answer to this arises from the cutoff point for squaring.  As in multiplication there exists a cutoff point, at which the 
time required for a Comba based squaring and a Karatsuba based squaring meet.  Due to the overhead inherent in the Karatsuba method, the cutoff 
point is fairly high.  For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.  

Consider squaring a 200 digit number with this technique.  It will be split into two 100 digit halves which are subsequently squared.  
The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm.  If Karatsuba multiplication
were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Initialize the following temporary mp\_ints:  $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
2.  If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1\beta^B + x0$ \\
3.  $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
\\
Calculate the three squares. \\
6.  $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
7.  $x1x1 \leftarrow x1^2$ \\
8.  $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\
9.  $t1 \leftarrow t1^2$ \\
\\
Compute the middle term. \\
10.  $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
11.  $t1 \leftarrow t1 - t2$ \\
\\
Compute final product. \\
12.  $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
13.  $x1x1 \leftarrow x1x1\beta^{2B}$ \\
14.  $t1 \leftarrow t1 + x0x0$ \\
15.  $b \leftarrow t1 + x1x1$ \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_sqr}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_sqr.}
This algorithm computes the square of an input $a$ using the Karatsuba technique.  This algorithm is very similar to the Karatsuba based
multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.

The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
placed just below the middle.  Step 3, 4 and 5 compute the two halves required using $B$
as the radix point.  The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.

By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2)  = 2 \cdot x0 \cdot x1$.
Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
this method is faster.  Assuming no further recursions occur, the difference can be estimated with the following inequality.

Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
machine clock cycles.}. 

\begin{equation}
5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
\end{equation}

For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$.  This implies that the following inequality should hold.
\begin{center}
\begin{tabular}{rcl}
${5n \over 3} + 3n^2 + 3n$     & $<$ & ${n \over 3} + 6n^2$ \\
${5 \over 3} + 3n + 3$     & $<$ & ${1 \over 3} + 6n$ \\
${13 \over 9}$     & $<$ & $n$ \\
\end{tabular}
\end{center}

This results in a cutoff point around $n = 2$.  As a consequence it is actually faster to compute the middle term the ``long way'' on processors
where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication.  On
the Intel P4 processor this ratio is 1:29 making this method even more beneficial.  The only common exception is the ARMv4 processor which has a
ratio of 1:7.  } than simpler operations such as addition.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul.  It uses the same inline style to copy and 
shift the input into the two halves.  The loop from line 54 to line 70 has been modified since only one input exists.  The \textbf{used}
count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin.  At this point $x1$ and $x0$ are valid equivalents
to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.  

By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered.  On the Athlon the cutoff point
is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}).  On slower processors such as the Intel P4
it is actually below the Comba limit (\textit{at 110 digits}).

This routine uses the same error trap coding style as mp\_karatsuba\_sqr.  As the temporary variables are initialized errors are 
redirected to the error trap higher up.  If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and 
mp\_clears are executed normally.

\subsection{Toom-Cook Squaring}
The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
instead of multiplication to find the five relations.  The reader is encouraged to read the description of the latter algorithm and try to 
derive their own Toom-Cook squaring algorithm.  

\subsection{High Level Squaring}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  If $a.used \ge TOOM\_SQR\_CUTOFF$ then  \\
\hspace{3mm}1.1  $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
2.  else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
\hspace{3mm}2.1  $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
3.  else \\
\hspace{3mm}3.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}3.2  If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
\hspace{6mm}3.2.1  $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr.  \\
\hspace{3mm}3.3  else \\
\hspace{6mm}3.3.1  $b \leftarrow a^2$ using algorithm s\_mp\_sqr.  \\
4.  $b.sign \leftarrow MP\_ZPOS$ \\
5.  Return the result of the unsigned squaring performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_sqr}
\end{figure}

\textbf{Algorithm mp\_sqr.}
This algorithm computes the square of the input using one of four different algorithms.  If the input is very large and has at least
\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used.  If
neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
                      & that have different number of digits in Karatsuba multiplication. \\
                      & \\
$\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\
                      & of double products and at most one square is stated.  Prove this statement. \\
                      & \\                      
$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
                      & \\
$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
                      & \\ 
$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
                      & required for equation $6.7$ to be true.  \\
                      & \\
$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
                      & compute subsets of the columns in each thread.  Determine a cutoff point where \\
                      & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
                      &\\
$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook.  You must \\
                      & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
                      & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
                      & \\
\end{tabular}

\chapter{Modular Reduction}
\section{Basics of Modular Reduction}
\index{modular residue}
Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, 
such as factoring.  Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set.  A number $a$ is said to be \textit{reduced}
modulo another number $b$ by finding the remainder of the division $a/b$.  Full integer division with remainder is a topic to be covered 
in~\ref{sec:division}.

Modular reduction is equivalent to solving for $r$ in the following equation.  $a = bq + r$ where $q = \lfloor a/b \rfloor$.  The result 
$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$.  In other vernacular $r$ is known as the 
``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
other forms of residues.  

Modular reductions are normally used to create either finite groups, rings or fields.  The most common usage for performance driven modular reductions 
is in modular exponentiation algorithms.  That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible.  This operation is used in the 
RSA and Diffie-Hellman public key algorithms, for example.  Modular multiplication and squaring also appears as a fundamental operation in 
elliptic curve cryptographic algorithms.  As will be discussed in the subsequent chapter there exist fast algorithms for computing modular 
exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications.  These algorithms will produce partial results in the 
range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms.   They have also been used to create redundancy check 
algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.  

\section{The Barrett Reduction}
The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
division.  Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to 

\begin{equation}
c = a - b \cdot \lfloor a/b \rfloor
\end{equation}

Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper 
targeted the DSP56K processor.}  intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal.  However, 
DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.  
It would take another common optimization to optimize the algorithm.

\subsection{Fixed Point Arithmetic}
The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers.  Fixed
point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were 
fairly slow if not unavailable.   The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit 
integer and a $q$-bit fraction part (\textit{where $p+q = k$}).  

In this system a $k$-bit integer $n$ would actually represent $n/2^q$.  For example, with $q = 4$ the integer $n = 37$ would actually represent the
value $2.3125$.  To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by 
moving the implied decimal point back to where it should be.  For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted 
to fixed point first by multiplying by $2^q$.  Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the 
fixed point representation of $5$.  The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.  

This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
of two fixed point numbers.  Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal.  If $2^q$ is 
equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic.  Using this fact dividing an integer 
$a$ by another integer $b$ can be achieved with the following expression.

\begin{equation}
\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

The precision of the division is proportional to the value of $q$.  If the divisor $b$ is used frequently as is the case with 
modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift.  Both operations
are considerably faster than division on most processors.  

Consider dividing $19$ by $5$.  The correct result is $\lfloor 19/5 \rfloor = 3$.  With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
leads to a product of $19$ which when divided by $2^q$ produces $2$.  However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct.  The value of $2^q$ must be close to or ideally
larger than the dividend.  In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
to work correctly.  Plugging this form of divison into the original equation the following modular residue equation arises.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol.  Using the $\mu$
variable also helps re-inforce the idea that it is meant to be computed once and re-used.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
\end{equation}

Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one.  In the context of Barrett
reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
precision.  

Let $n$ represent the number of digits in $b$.  This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and 
another $n^2$ single precision multiplications to find the residue.  In total $3n^2$ single precision multiplications are required to 
reduce the number.  

For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$.  Consider reducing
$a = 180388626447$ modulo $b$ using the above reduction equation.  The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.

\subsection{Choosing a Radix Point}
Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications.  If that were the best
that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.  
See~\ref{sec:division} for further details.} might as well be used in its place.  The key to optimizing the reduction is to reduce the precision of
the initial multiplication that finds the quotient.  

Let $a$ represent the number of which the residue is sought.  Let $b$ represent the modulus used to find the residue.  Let $m$ represent
the number of digits in $b$.  For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if 
two $m$-digit numbers have been multiplied.  Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer.  Digits below the 
$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$.  Another way to
express this is by re-writing $a$ as two parts.  If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then 
${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$.  Since $a'$ is bound to be less than $b$ the quotient
is bound by $0 \le {a' \over b} < 1$.

Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero.  However, if the digits 
``might as well be zero'' they might as well not be there in the first place.  Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
with the irrelevant digits trimmed.  Now the modular reduction is trimmed to the almost equivalent equation

\begin{equation}
c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
\end{equation}

Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the 
exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$.  If the optimization had not been performed the divisor 
would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two.  The original fixed point quotient can be off
by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
can be off by an additional value of one for a total of at most two.  This implies that 
$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  By first subtracting $b$ times the quotient and then conditionally subtracting 
$b$ once or twice the residue is found.

The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
precision multiplications, ignoring the subtractions required.  In total $2m^2 + m$ single precision multiplications are required to find the residue.  
This is considerably faster than the original attempt.

For example, let $\beta = 10$ represent the radix of the digits.  Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ 
represent the value of which the residue is desired.  In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.  
With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$.  The quotient is then 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$.  Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ 
is found.  

\subsection{Trimming the Quotient}
So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications.  As 
it stands now the algorithm is already fairly fast compared to a full integer division algorithm.  However, there is still room for
optimization.  

After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
half of the product.  It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision 
multiplications.  If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.  
In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.  

The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number.  Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
multiplications would be required.  Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.  

\subsection{Trimming the Residue}
After the quotient has been calculated it is used to reduce the input.  As previously noted the algorithm is not exact and it can be off by a small
multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  If $b$ is $m$ digits than the 
result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
implicitly zero.  

The next optimization arises from this very fact.  Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed.  Similarly the value of $a$ can
be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well.  A multiplication that produces 
only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.  

With both optimizations in place the algorithm is the algorithm Barrett proposed.  It requires $m^2 + 2m - 1$ single precision multiplications which
is considerably faster than the straightforward $3m^2$ method.  

\subsection{The Barrett Algorithm}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
\textbf{Output}.  $a \mbox{ (mod }b\mbox{)}$ \\
\hline \\
Let $m$ represent the number of digits in $b$.  \\
1.  Make a copy of $a$ and store it in $q$.  (\textit{mp\_init\_copy}) \\
2.  $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
\\
Produce the quotient. \\
3.  $q \leftarrow q \cdot \mu$  (\textit{note: only produce digits at or above $m-1$}) \\
4.  $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
\\
Subtract the multiple of modulus from the input. \\
5.  $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
6.  $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
7.  $a \leftarrow a - q$ (\textit{mp\_sub}) \\
\\
Add $\beta^{m+1}$ if a carry occured. \\
8.  If $a < 0$ then (\textit{mp\_cmp\_d}) \\
\hspace{3mm}8.1  $q \leftarrow 1$ (\textit{mp\_set}) \\
\hspace{3mm}8.2  $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
\hspace{3mm}8.3  $a \leftarrow a + q$ \\
\\
Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
9.  While $a \ge b$ do (\textit{mp\_cmp}) \\
\hspace{3mm}9.1  $c \leftarrow a - b$ \\
10.  Clear $q$. \\
11.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce}
\end{figure}

\textbf{Algorithm mp\_reduce.}
This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm.  It is loosely based on algorithm 14.42 of HAC
\cite[pp.  602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}.  The algorithm has several restrictions and assumptions which must 
be adhered to for the algorithm to work.

First the modulus $b$ is assumed to be positive and greater than one.  If the modulus were less than or equal to one than subtracting
a multiple of it would either accomplish nothing or actually enlarge the input.  The input $a$ must be in the range $0 \le a < b^2$ in order
for the quotient to have enough precision.  If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish.  The value of $\mu$ is passed as an argument to this 
algorithm and is assumed to be calculated and stored before the algorithm is used.  

Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position.  An algorithm called 
$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task.  The algorithm is based on $s\_mp\_mul\_digs$ except that
instead of stopping at a given level of precision it starts at a given level of precision.  This optimal algorithm can only be used if the number
of digits in $b$ is very much smaller than $\beta$.  

While it is known that 
$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied 
``borrow'' from the higher digits might leave a negative result.  After the multiple of the modulus has been subtracted from $a$ the residue must be 
fixed up in case it is negative.  The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.  

The while loop at step 9 will subtract $b$ until the residue is less than $b$.  If the algorithm is performed correctly this step is 
performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up.  This essentially halves
the number of single precision multiplications required.  However, the optimization is only safe if $\beta$ is much larger than the number of digits
in the modulus.  In the source code this is evaluated on lines 36 to 44 where algorithm s\_mp\_mul\_high\_digs is used when it is
safe to do so.  

\subsection{The Barrett Setup Algorithm}
In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance.  Ideally this value should be computed once and stored for
future use so that the Barrett algorithm can be used without delay.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_setup}. \\
\textbf{Input}.   mp\_int $a$ ($a > 1$)  \\
\textbf{Output}.  $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
\hline \\
1.  $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot  m}$ (\textit{mp\_2expt}) \\
2.  $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_setup.}
This algorithm computes the reciprocal $\mu$ required for Barrett reduction.  First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot  m}$ which
is equivalent and much faster.  The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This simple routine calculates the reciprocal $\mu$ required by Barrett reduction.  Note the extended usage of algorithm mp\_div where the variable
which would received the remainder is passed as NULL.  As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the 
remainder to be passed as NULL meaning to ignore the value.  

\section{The Montgomery Reduction}
Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting 
form of reduction in common use.  It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a 
residue times a constant.  However, as perplexing as this may sound the algorithm is relatively simple and very efficient.  

Throughout this entire section the variable $n$ will represent the modulus used to form the residue.  As will be discussed shortly the value of
$n$ must be odd.  The variable $x$ will represent the quantity of which the residue is sought.  Similar to the Barrett algorithm the input
is restricted to $0 \le x < n^2$.  To begin the description some simple number theory facts must be established.

\textbf{Fact 1.}  Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$.  Another way
to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$.  Adding zero will not change the value of the residue.  

\textbf{Fact 2.}  If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$.  Actually
this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to 
multiplication by $k^{-1}$ modulo $n$.  

From these two simple facts the following simple algorithm can be derived.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction}. \\
\textbf{Input}.   Integer $x$, $n$ and $k$ \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $1$ to $k$ do \\
\hspace{3mm}1.1  If $x$ is odd then \\
\hspace{6mm}1.1.1  $x \leftarrow x + n$ \\
\hspace{3mm}1.2  $x \leftarrow x/2$ \\
2.  Return $x$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction}
\end{figure}

The algorithm reduces the input one bit at a time using the two congruencies stated previously.  Inside the loop $n$, which is odd, is
added to $x$ if $x$ is odd.  This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two.  Since
$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$.  Let $r$ represent the 
final result of the Montgomery algorithm.  If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to 
$0 \le r < \lfloor x/2^k \rfloor + n$.  As a result at most a single subtraction is required to get the residue desired.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
\hline $2$ & $x/2 = 1453$ \\
\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
\hline $5$ & $x/2 = 278$ \\
\hline $6$ & $x/2 = 139$ \\
\hline $7$ & $x + n = 396$, $x/2 = 198$ \\
\hline $8$ & $x/2 = 99$ \\
\hline $9$ & $x + n = 356$, $x/2 = 178$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (I)}
\label{fig:MONT1}
\end{figure}

Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$).  The result of 
the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$.  When $r$ is multiplied by $2^9$ modulo $257$ the correct residue 
$r \equiv 158$ is produced.  

Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$.  The current algorithm requires $2k^2$ single precision shifts
and $k^2$ single precision additions.  At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.  
Fortunately there exists an alternative representation of the algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ ($2^k > n$) \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $1$ to $k$ do \\
\hspace{3mm}1.1  If the $t$'th bit of $x$ is one then \\
\hspace{6mm}1.1.1  $x \leftarrow x + 2^tn$ \\
2.  Return $x/2^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified I)}
\end{figure}

This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2.  The number of single
precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|r|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
\hline -- & $5555$ & $1010110110011$ \\
\hline $1$ & $x + 2^{0}n = 5812$ &  $1011010110100$ \\
\hline $2$ & $5812$ & $1011010110100$ \\
\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
\hline $5$ & $8896$ & $10001011000000$ \\
\hline $6$ & $8896$ & $10001011000000$ \\
\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
\hline $8$ & $25344$ & $110001100000000$ \\
\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\
\hline -- & $x/2^k = 178$ & \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (II)}
\label{fig:MONT2}
\end{figure}

Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. 
With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the 
loop.  Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed.  In those iterations the $t$'th bit of $x$ is 
zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.  

\subsection{Digit Based Montgomery Reduction}
Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis.  Consider the
previous algorithm re-written to compute the Montgomery reduction in this new fashion.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ ($\beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1  $x \leftarrow x + \mu n \beta^t$ \\
2.  Return $x/\beta^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified II)}
\end{figure}

The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue.  If the first digit of 
the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit.  This
problem breaks down to solving the following congruency.  

\begin{center}
\begin{tabular}{rcl}
$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\end{tabular}
\end{center}

In each iteration of the loop on step 1 a new value of $\mu$ must be calculated.  The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used 
extensively in this algorithm and should be precomputed.  Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.  

For example, let $\beta = 10$ represent the radix.  Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$.  Let $x = 33$ 
represent the value to reduce.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
\hline --                 & $33$ & --\\
\hline $0$                 & $33 + \mu n = 50$ & $1$ \\
\hline $1$                 & $50 + \mu n \beta = 900$ & $5$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Montgomery Reduction}
\end{figure}

The final result $900$ is then divided by $\beta^k$ to produce the final result $9$.  The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ 
which implies the result is not the modular residue of $x$ modulo $n$.  However, recall that the residue is actually multiplied by $\beta^{-k}$ in
the algorithm.  To get the true residue the value must be multiplied by $\beta^k$.  In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.  

\subsection{Baseline Montgomery Reduction}
The baseline Montgomery reduction algorithm will produce the residue for any size input.  It is designed to be a catch-all algororithm for 
Montgomery reductions.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  $digs \leftarrow 2n.used + 1$ \\
2.  If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
\hspace{3mm}2.1  Use algorithm fast\_mp\_montgomery\_reduce instead. \\
\\
Setup $x$ for the reduction. \\
3.  If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
4.  $x.used \leftarrow digs$ \\
\\
Eliminate the lower $k$ digits. \\
5.  For $ix$ from $0$ to $k - 1$ do \\
\hspace{3mm}5.1  $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.2  $u \leftarrow 0$ \\
\hspace{3mm}5.3  For $iy$ from $0$ to $k - 1$ do \\
\hspace{6mm}5.3.1  $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
\hspace{6mm}5.3.2  $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.3.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.4  While $u > 0$ do \\
\hspace{6mm}5.4.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}5.4.2  $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
\hspace{6mm}5.4.4  $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
\\
Divide by $\beta^k$ and fix up as required. \\
6.  $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
7.  If $x \ge n$ then \\
\hspace{3mm}7.1  $x \leftarrow x - n$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm mp\_montgomery\_reduce.}
This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm.  The algorithm is loosely based
on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop.  The
restrictions on this algorithm are fairly easy to adapt to.  First $0 \le x < n^2$ bounds the input to numbers in the same range as 
for the Barrett algorithm.  Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$.  $\rho$ must be calculated in
advance of this algorithm.  Finally the variable $k$ is fixed and a pseudonym for $n.used$.  

Step 2 decides whether a faster Montgomery algorithm can be used.  It is based on the Comba technique meaning that there are limits on
the size of the input.  This algorithm is discussed in sub-section 6.3.3.

Step 5 is the main reduction loop of the algorithm.  The value of $\mu$ is calculated once per iteration in the outer loop.  The inner loop
calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits.  Both the addition and
multiplication are performed in the same loop to save time and memory.  Step 5.4 will handle any additional carries that escape the inner loop.

Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications 
in the inner loop.  In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
multiplications.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This is the baseline implementation of the Montgomery reduction algorithm.  Lines 31 to 36 determine if the Comba based
routine can be used instead.  Line 47 computes the value of $\mu$ for that particular iteration of the outer loop.  

The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop.  The alias $tmpx$ refers to the $ix$'th digit of $x$ and
the alias $tmpn$ refers to the modulus $n$.  

\subsection{Faster ``Comba'' Montgomery Reduction}

The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
nature of the inner loop.  The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
technique.  The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
a $k \times 1$ product $k$ times. 

The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$.  This means the 
carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit.  The solution as it turns out is very simple.  
Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.  

With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
the speed of the algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
1.  if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
Copy the digits of $x$ into the array $\hat W$ \\
2.  For $ix$ from $0$ to $x.used - 1$ do \\
\hspace{3mm}2.1  $\hat W_{ix} \leftarrow x_{ix}$ \\
3.  For $ix$ from $x.used$ to $2n.used - 1$ do \\
\hspace{3mm}3.1  $\hat W_{ix} \leftarrow 0$ \\
Elimiate the lower $k$ digits. \\
4.  for $ix$ from $0$ to $n.used - 1$ do \\
\hspace{3mm}4.1  $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.2  For $iy$ from $0$ to $n.used - 1$ do \\
\hspace{6mm}4.2.1  $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
\hspace{3mm}4.3  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Propagate carries upwards. \\
5.  for $ix$ from $n.used$ to $2n.used + 1$ do \\
\hspace{3mm}5.1  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Shift right and reduce modulo $\beta$ simultaneously. \\
6.  for $ix$ from $0$ to $n.used + 1$ do \\
\hspace{3mm}6.1  $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
Zero excess digits and fixup $x$. \\
7.  if $x.used > n.used + 1$ then do \\
\hspace{3mm}7.1  for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
\hspace{6mm}7.1.1  $x_{ix} \leftarrow 0$ \\
8.  $x.used \leftarrow n.used + 1$ \\
9.  Clamp excessive digits of $x$. \\
10.  If $x \ge n$ then \\
\hspace{3mm}10.1  $x \leftarrow x - n$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm fast\_mp\_montgomery\_reduce.}
This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique.  It is on most computer platforms significantly
faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}).  The algorithm has the same restrictions
on the input as the baseline reduction algorithm.  An additional two restrictions are imposed on this algorithm.  The number of digits $k$ in the 
the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$.   When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
a modulus of at most $3,556$ bits in length.  

As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product.  It is initially filled with the
contents of $x$ with the excess digits zeroed.  The reduction loop is very similar the to the baseline loop at heart.  The multiplication on step
4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$.  Some multipliers such
as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce.  By performing
a single precision multiplication instead half the amount of time is spent.

Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work.  That is what step
4.3 will do.  In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards.  Note
how the upper bits of those same words are not reduced modulo $\beta$.  This is because those values will be discarded shortly and there is no
point.

Step 5 will propagate the remainder of the carries upwards.  On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
stored in the destination $x$.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The $\hat W$ array is first filled with digits of $x$ on line 48 then the rest of the digits are zeroed on line 55.  Both loops share
the same alias variables to make the code easier to read.  

The value of $\mu$ is calculated in an interesting fashion.  First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit.  This
forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision.   Line 110 fixes the carry 
for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.

The for loop on line 109 propagates the rest of the carries upwards through the columns.  The for loop on line 126 reduces the columns
modulo $\beta$ and shifts them $k$ places at the same time.  The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.  

\subsection{Montgomery Setup}
To calculate the variable $\rho$ a relatively simple algorithm will be required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_setup}. \\
\textbf{Input}.   mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
\textbf{Output}.  $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\hline \\
1.  $b \leftarrow n_0$ \\
2.  If $b$ is even return(\textit{MP\_VAL}) \\
3.  $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\
4.  for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
\hspace{3mm}4.1  $x \leftarrow x \cdot (2 - bx)$ \\
5.  $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_setup} 
\end{figure}

\textbf{Algorithm mp\_montgomery\_setup.}
This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms.  It uses a very interesting trick 
to calculate $1/n_0$ when $\beta$ is a power of two.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This source code computes the value of $\rho$ required to perform Montgomery reduction.  It has been modified to avoid performing excess
multiplications when $\beta$ is not the default 28-bits.  

\section{The Diminished Radix Algorithm}
The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
or Montgomery methods for certain forms of moduli.  The technique is based on the following simple congruence.

\begin{equation}
(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
\end{equation}

This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive.  It used the fact that if $n = 2^{31}$ and $k=1$ that 
then a x86 multiplier could produce the 62-bit product and use  the ``shrd'' instruction to perform a double-precision right shift.  The proof
of the above equation is very simple.  First write $x$ in the product form.

\begin{equation}
x = qn + r
\end{equation}

Now reduce both sides modulo $(n - k)$.

\begin{equation}
x \equiv qk + r  \mbox{ (mod }(n-k)\mbox{)}
\end{equation}

The variable $n$ reduces modulo $n - k$ to $k$.  By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ 
into the equation the original congruence is reproduced, thus concluding the proof.  The following algorithm is based on this observation.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Diminished Radix Reduction}. \\
\textbf{Input}.   Integer $x$, $n$, $k$ \\
\textbf{Output}.  $x \mbox{ mod } (n - k)$ \\
\hline \\
1.  $q \leftarrow \lfloor x / n \rfloor$ \\
2.  $q \leftarrow k \cdot q$ \\
3.  $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
4.  $x \leftarrow x + q$ \\
5.  If $x \ge (n - k)$ then \\
\hspace{3mm}5.1  $x \leftarrow x - (n - k)$ \\
\hspace{3mm}5.2  Goto step 1. \\
6.  Return $x$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Diminished Radix Reduction}
\label{fig:DR}
\end{figure}

This algorithm will reduce $x$ modulo $n - k$ and return the residue.  If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
once or twice and occasionally three times.  For simplicity sake the value of $x$ is bounded by the following simple polynomial.

\begin{equation} 
0 \le x < n^2 + k^2 - 2nk
\end{equation}

The true bound is  $0 \le x < (n - k - 1)^2$ but this has quite a few more terms.  The value of $q$ after step 1 is bounded by the following.

\begin{equation}
q < n - 2k - k^2/n
\end{equation}

Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero.  The value of $x$ after step 3 is bounded trivially as
$0 \le x < n$.  By step four the sum $x + q$ is bounded by 

\begin{equation}
0 \le q + x < (k + 1)n - 2k^2 - 1
\end{equation}

With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3.  After the second pass it is highly unlike that the
sum in step 4 will exceed $n - k$.  In practice fewer than three passes of the algorithm are required to reduce virtually every input in the 
range $0 \le x < (n - k - 1)^2$.  

\begin{figure}
\begin{small}
\begin{center}
\begin{tabular}{|l|}
\hline
$x = 123456789, n = 256, k = 3$ \\
\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
$q \leftarrow q*k = 1446759$ \\
$x \leftarrow x \mbox{ mod } n = 21$ \\
$x \leftarrow x + q = 1446780$ \\
$x \leftarrow x - (n - k) = 1446527$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 5650$ \\
$q \leftarrow q*k = 16950$ \\
$x \leftarrow x \mbox{ mod } n = 127$ \\
$x \leftarrow x + q = 17077$ \\
$x \leftarrow x - (n - k) = 16824$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 65$ \\
$q \leftarrow q*k = 195$ \\
$x \leftarrow x \mbox{ mod } n = 184$ \\
$x \leftarrow x + q = 379$ \\
$x \leftarrow x - (n - k) = 126$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example Diminished Radix Reduction}
\label{fig:EXDR}
\end{figure}

Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$.  Note that even while $x$
is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast.  In this case only
three passes were required to find the residue $x \equiv 126$.


\subsection{Choice of Moduli}
On the surface this algorithm looks like a very expensive algorithm.  It requires a couple of subtractions followed by multiplication and other
modular reductions.  The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.

Division in general is a very expensive operation to perform.  The one exception is when the division is by a power of the radix of representation used.  
Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right.  Similarly division 
by two (\textit{or powers of two}) is very simple for binary computers to perform.  It would therefore seem logical to choose $n$ of the form $2^p$ 
which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.  

However, there is one operation related to division of power of twos that is even faster than this.  If $n = \beta^p$ then the division may be 
performed by moving whole digits to the right $p$ places.  In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.  
Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.  

Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
modulus'' will refer to a modulus of the form $2^p - k$.  The word ``restricted'' in this case refers to the fact that it is based on the 
$2^p$ logic except $p$ must be a multiple of $lg(\beta)$.  

\subsection{Choice of $k$}
Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
in step 2 is the most expensive operation.  Fortunately the choice of $k$ is not terribly limited.  For all intents and purposes it might
as well be a single digit.  The smaller the value of $k$ is the faster the algorithm will be.  

\subsection{Restricted Diminished Radix Reduction}
The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$.  This algorithm can reduce 
an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}.  The implementation
of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition 
of $x$ and $q$.  The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular 
exponentiations are performed.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_reduce}. \\
\textbf{Input}.   mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
\textbf{Output}.  $x \mbox{ mod } n$ \\
\hline \\
1.  $m \leftarrow n.used$ \\
2.  If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
3.  $\mu \leftarrow 0$ \\
4.  for $i$ from $0$ to $m - 1$ do \\
\hspace{3mm}4.1  $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
\hspace{3mm}4.2  $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  $x_{m} \leftarrow \mu$ \\
6.  for $i$ from $m + 1$ to $x.used - 1$ do \\
\hspace{3mm}6.1  $x_{i} \leftarrow 0$ \\
7.  Clamp excess digits of $x$. \\
8.  If $x \ge n$ then \\
\hspace{3mm}8.1  $x \leftarrow x - n$ \\
\hspace{3mm}8.2  Goto step 3. \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_reduce}
\end{figure}

\textbf{Algorithm mp\_dr\_reduce.}
This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$.  It has similar restrictions to that of the Barrett reduction
with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.  

This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization.  The division by $\beta^m$, multiplication by $k$
and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4.  The division by $\beta^m$ is emulated by accessing
the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position.  After the loop the $m$'th
digit is set to the carry and the upper digits are zeroed.  Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to 
$x$ before the addition of the multiple of the upper half.  

At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required.  First $n$ is subtracted from $x$ and then the algorithm resumes
at step 3.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$.  The label on line 52 is where
the algorithm will resume if further reduction passes are required.  In theory it could be placed at the top of the function however, the size of
the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.  

The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits.  By reading digits from $x$ offset by $m$ digits
a division by $\beta^m$ can be simulated virtually for free.  The loop on line 64 performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
in this algorithm.

By line 67 the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed.  Similarly by line 74 the 
same pointer will point to the $m+1$'th digit where the zeroes will be placed.  

Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.  
With the same logic at line 81 the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
as well.  Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
does not need to be checked.

\subsubsection{Setup}
To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required.  This algorithm is not really complicated but provided for
completeness.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_setup}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $k = \beta - n_0$ \\
\hline \\
1.  $k \leftarrow \beta - n_0$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_setup}
\end{figure}

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsubsection{Modulus Detection}
Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus.  An integer is said to be
of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $1$ if $n$ is in D.R form, $0$ otherwise \\
\hline
1.  If $n.used < 2$ then return($0$). \\
2.  for $ix$ from $1$ to $n.used - 1$ do \\
\hspace{3mm}2.1  If $n_{ix} \ne \beta - 1$ return($0$). \\
3.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_is\_modulus}
\end{figure}

\textbf{Algorithm mp\_dr\_is\_modulus.}
This algorithm determines if a value is in Diminished Radix form.  Step 1 rejects obvious cases where fewer than two digits are
in the mp\_int.  Step 2 tests all but the first digit to see if they are equal to $\beta - 1$.  If the algorithm manages to get to
step 3 then $n$ must be of Diminished Radix form.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsection{Unrestricted Diminished Radix Reduction}
The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$.  This algorithm
is a straightforward adaptation of algorithm~\ref{fig:DR}.

In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead.  However, this new
algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k}. \\
\textbf{Input}.   mp\_int $a$ and $n$.  mp\_digit $k$  \\
\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
\textbf{Output}.  $a \mbox{ (mod }n\mbox{)}$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  While $a \ge n$ do \\
\hspace{3mm}2.1  $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
\hspace{3mm}2.2  $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
\hspace{3mm}2.3  $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
\hspace{3mm}2.4  $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.5  If $a \ge n$ then do \\
\hspace{6mm}2.5.1  $a \leftarrow a - n$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k.}
This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$.  Division by $2^p$ is emulated with a right
shift which makes the algorithm fairly inexpensive to use.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$.  The call to mp\_div\_2d
on line 31 calculates both the quotient $q$ and the remainder $a$ required.  By doing both in a single function call the code size
is kept fairly small.  The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
any multiplications.  

The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are 
positive.  By using the unsigned versions the overhead is kept to a minimum.  

\subsubsection{Unrestricted Setup}
To setup this reduction algorithm the value of $k = 2^p - n$ is required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $k = 2^p - n$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
3.  $x \leftarrow x - n$ (\textit{mp\_sub}) \\
4.  $k \leftarrow x_0$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k\_setup.}
This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k.  By making a temporary variable $x$ equal to $2^p$ a subtraction
is sufficient to solve for $k$.  Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsubsection{Unrestricted Detection}
An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.

\begin{enumerate}
\item  The number has only one digit.
\item  The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
\end{enumerate}

If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$.   If the input is only
one digit than it will always be of the correct form.  Otherwise all of the bits above the first digit must be one.  This arises from the fact
that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
significant bit.  The resulting sum will be a power of two.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $1$ if of proper form, $0$ otherwise \\
\hline
1.  If $n.used = 0$ then return($0$). \\
2.  If $n.used = 1$ then return($1$). \\
3.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
4.  for $x$ from $lg(\beta)$ to $p$ do \\
\hspace{3mm}4.1  If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
5.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_is\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_is\_2k.}
This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}



\section{Algorithm Comparison}
So far three very different algorithms for modular reduction have been discussed.  Each of the algorithms have their own strengths and weaknesses
that makes having such a selection very useful.  The following table sumarizes the three algorithms along with comparisons of work factors.  Since
all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.  

\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
\hline Barrett    & $m^2 + 2m - 1$ & None              & $79$ & $1087$ & $4223$ \\
\hline Montgomery & $m^2 + m$      & $n$ must be odd   & $72$ & $1056$ & $4160$ \\
\hline D.R.       & $2m$           & $n = \beta^m - k$ & $16$ & $64$   & $128$  \\
\hline
\end{tabular}
\end{small}
\end{center}

In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete.  However, in practice since Montgomery
reduction can be written as a single function with the Comba technique it is much faster.  Barrett reduction suffers from the overhead of
calling the half precision multipliers, addition and division by $\beta$ algorithms.

For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice.  The one set of algorithms where Diminished Radix reduction truly
shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}.  In these algorithms
primes of the form $\beta^m - k$ can be found and shared amongst users.  These primes will allow the Diminished Radix algorithm to be used in
modular exponentiation to greatly speed up the operation.



\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
                     & calculates the correct value of $\rho$. \\
                     & \\
$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly.  \\
                     & \\
$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
                     & (\textit{figure~\ref{fig:DR}}) terminates.  Also prove the probability that it will \\
                     & terminate within $1 \le k \le 10$ iterations. \\
                     & \\
\end{tabular}                     


\chapter{Exponentiation}
Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$.  A variant of exponentiation, computed
in a finite field or ring, is called modular exponentiation.  This latter style of operation is typically used in public key 
cryptosystems such as RSA and Diffie-Hellman.  The ability to quickly compute modular exponentiations is of great benefit to any
such cryptosystem and many methods have been sought to speed it up.

\section{Exponentiation Basics}
A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired.  However, as $b$ grows in size
the number of multiplications becomes prohibitive.  Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
with a $1024$-bit key.  Such a calculation could never be completed as it would take simply far too long.

Fortunately there is a very simple algorithm based on the laws of exponents.  Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
are two trivial relationships between the base and the exponent.  Let $b_i$ represent the $i$'th bit of $b$ starting from the least 
significant bit.  If $b$ is a $k$-bit integer than the following equation is true.

\begin{equation}
a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
\end{equation}

By taking the base $a$ logarithm of both sides of the equation the following equation is the result.

\begin{equation}
b = \sum_{i=0}^{k-1}2^i \cdot b_i
\end{equation}

The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
$a^{2^{i+1}}$.  This observation forms the basis of essentially all fast exponentiation algorithms.  It requires $k$ squarings and on average
$k \over 2$ multiplications to compute the result.  This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.

While this current method is a considerable speed up there are further improvements to be made.  For example, the $a^{2^i}$ term does not need to 
be computed in an auxilary variable.  Consider the following equivalent algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Left to Right Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$ and $k$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $k - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^2$ \\
\hspace{3mm}2.2  $c \leftarrow c \cdot a^{b_i}$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Left to Right Exponentiation}
\label{fig:LTOR}
\end{figure}

This algorithm starts from the most significant bit and works towards the least significant bit.  When the $i$'th bit of $b$ is set $a$ is
multiplied against the current product.  In each iteration the product is squared which doubles the exponent of the individual terms of the
product.  

For example, let $b = 101100_2 \equiv 44_{10}$.  The following chart demonstrates the actions of the algorithm.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|}
\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
\hline - & $1$ \\
\hline $5$ & $a$ \\
\hline $4$ & $a^2$ \\
\hline $3$ & $a^4 \cdot a$ \\
\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Left to Right Exponentiation}
\end{figure}

When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation.  This particular algorithm is 
called ``Left to Right'' because it reads the exponent in that order.  All of the exponentiation algorithms that will be presented are of this nature.  

\subsection{Single Digit Exponentiation}
The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit.  It is intended 
to be used when a small power of an input is required (\textit{e.g. $a^5$}).  It is faster than simply multiplying $b - 1$ times for all values of 
$b$ that are greater than three.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_expt\_d}. \\
\textbf{Input}.   mp\_int $a$ and mp\_digit $b$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
2.  $c \leftarrow 1$ (\textit{mp\_set}) \\
3.  for $x$ from 1 to $lg(\beta)$ do \\
\hspace{3mm}3.1  $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
\hspace{3mm}3.2  If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
\hspace{6mm}3.2.1  $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
\hspace{3mm}3.3  $b \leftarrow b << 1$ \\
4.  Clear $g$. \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_expt\_d}
\end{figure}

\textbf{Algorithm mp\_expt\_d.}
This algorithm computes the value of $a$ raised to the power of a single digit $b$.  It uses the left to right exponentiation algorithm to
quickly compute the exponentiation.  It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the 
exponent is a fixed width.  

A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$.  The result is set to the initial value of 
$1$ in the subsequent step.

Inside the loop the exponent is read from the most significant bit first down to the least significant bit.  First $c$ is invariably squared
on step 3.1.  In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$.  The value
of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit.  In effect each
iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Line 29 sets the initial value of the result to $1$.  Next the loop on line 31 steps through each bit of the exponent starting from
the most significant down towards the least significant. The invariant squaring operation placed on line 33 is performed first.  After 
the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set.  The shift on line
47 moves all of the bits of the exponent upwards towards the most significant location.  

\section{$k$-ary Exponentiation}
When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
slower than squaring.  Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$.  Suppose instead it referred to
the $i$'th $k$-bit digit of the exponent of $b$.  For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
computes the same exponentiation.  A group of $k$ bits from the exponent is called a \textit{window}.  That is it is a small window on only a
portion of the entire exponent.  Consider the following modification to the basic left to right exponentiation algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{$k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^{2^k} $ \\
\hspace{3mm}2.2  Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
\hspace{3mm}2.3  $c \leftarrow c \cdot a^g$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{$k$-ary Exponentiation}
\label{fig:KARY}
\end{figure}

The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times.  If the values of $a^g$ for $0 < g < 2^k$ have been
precomputed this algorithm requires only $t$ multiplications and $tk$ squarings.  The table can be generated with $2^{k - 1} - 1$ squarings and
$2^{k - 1} + 1$ multiplications.  This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.  
However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.

Suppose $k = 4$ and $t = 100$.  This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation.  The
original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value.  The total number of squarings
has increased slightly but the number of multiplications has nearly halved.

\subsection{Optimal Values of $k$}
An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$.  The simplest
approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result.  Table~\ref{fig:OPTK} lists optimal values of $k$
for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
\hline $16$ & $2$ & $27$ & $24$ \\
\hline $32$ & $3$ & $49$ & $48$ \\
\hline $64$ & $3$ & $92$ & $96$ \\
\hline $128$ & $4$ & $175$ & $192$ \\
\hline $256$ & $4$ & $335$ & $384$ \\
\hline $512$ & $5$ & $645$ & $768$ \\
\hline $1024$ & $6$ & $1257$ & $1536$ \\
\hline $2048$ & $6$ & $2452$ & $3072$ \\
\hline $4096$ & $7$ & $4808$ & $6144$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for $k$-ary Exponentiation}
\label{fig:OPTK}
\end{figure}

\subsection{Sliding-Window Exponentiation}
A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$.  Essentially
this is a table for all values of $g$ where the most significant bit of $g$ is a one.  However, in order for this to be allowed in the 
algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.  

Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
\hline $16$ & $3$ & $24$ & $27$ \\
\hline $32$ & $3$ & $45$ & $49$ \\
\hline $64$ & $4$ & $87$ & $92$ \\
\hline $128$ & $4$ & $167$ & $175$ \\
\hline $256$ & $5$ & $322$ & $335$ \\
\hline $512$ & $6$ & $628$ & $645$ \\
\hline $1024$ & $6$ & $1225$ & $1257$ \\
\hline $2048$ & $7$ & $2403$ & $2452$ \\
\hline $4096$ & $8$ & $4735$ & $4808$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for Sliding Window Exponentiation}
\label{fig:OPTK2}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  If the $i$'th bit of $b$ is a zero then \\
\hspace{6mm}2.1.1   $c \leftarrow c^2$ \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c \leftarrow c^{2^k}$ \\
\hspace{6mm}2.2.2  Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
\hspace{6mm}2.2.3  $c \leftarrow c \cdot a^g$ \\
\hspace{6mm}2.2.4  $i \leftarrow i - k$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Sliding Window $k$-ary Exponentiation}
\end{figure}

Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent.  While this
algorithm requires the same number of squarings it can potentially have fewer multiplications.  The pre-computed table $a^g$ is also half
the size as the previous table.  

Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms.  The first algorithm will divide the exponent up as 
the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$.  The second algorithm will break the 
exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$.  The single digit $0$ in the second representation are where
a single squaring took place instead of a squaring and multiplication.  In total the first method requires $10$ multiplications and $18$ 
squarings.  The second method requires $8$ multiplications and $18$ squarings.  

In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.  

\section{Modular Exponentiation}

Modular exponentiation is essentially computing the power of a base within a finite field or ring.  For example, computing 
$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation.  Instead of first computing $a^b$ and then reducing it 
modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.  

This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
one of the algorithms presented in chapter six.  

Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first.  This algorithm
will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}).  If no inverse exists the algorithm
terminates with an error.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  If $b.sign = MP\_NEG$ then \\
\hspace{3mm}2.1  $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
\hspace{3mm}2.2  $x' \leftarrow \vert x \vert$ \\
\hspace{3mm}2.3  Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
3.  if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
\hspace{3mm}3.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
4.  else \\
\hspace{3mm}4.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_exptmod}
\end{figure}

\textbf{Algorithm mp\_exptmod.}
The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod.  It is a sliding window $k$-ary algorithm 
which uses Barrett reduction to reduce the product modulo $p$.  The second algorithm mp\_exptmod\_fast performs the same operation 
except it uses either Montgomery or Diminished Radix reduction.  The two latter reduction algorithms are clumped in the same exponentiation
algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

In order to keep the algorithms in a known state the first step on line 29 is to reject any negative modulus as input.  If the exponent is
negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$.  The temporary variable $tmpG$ is assigned
the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$.  The algorithm will recuse with these new values with a positive
exponent.

If the exponent is positive the algorithm resumes the exponentiation.  Line 77 determines if the modulus is of the restricted Diminished Radix 
form.  If it is not line 70 attempts to determine if it is of a unrestricted Diminished Radix form.  The integer $dr$ will take on one
of three values.

\begin{enumerate}
\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
\item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
\end{enumerate}

Line 69 determines if the fast modular exponentiation algorithm can be used.  It is allowed if $dr \ne 0$ or if the modulus is odd.  Otherwise,
the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.  

\subsection{Barrett Modular Exponentiation}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  $k \leftarrow lg(x)$ \\
2.  $winsize \leftarrow  \left \lbrace \begin{array}{ll}
                              2 &  \mbox{if }k \le 7 \\
                              3 &  \mbox{if }7 < k \le 36 \\
                              4 &  \mbox{if }36 < k \le 140 \\
                              5 &  \mbox{if }140 < k \le 450 \\
                              6 &  \mbox{if }450 < k \le 1303 \\
                              7 &  \mbox{if }1303 < k \le 3529 \\
                              8 &  \mbox{if }3529 < k \\
                              \end{array} \right .$ \\
3.  Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
4.  Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
5.  $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
\\
Setup the table of small powers of $g$.  First find $g^{2^{winsize}}$ and then all multiples of it. \\
6.  $k \leftarrow 2^{winsize - 1}$ \\
7.  $M_{k} \leftarrow M_1$ \\
8.  for $ix$ from 0 to $winsize - 2$ do \\
\hspace{3mm}8.1  $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr})  \\
\hspace{3mm}8.2  $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
9.  for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
\hspace{3mm}9.1  $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
\hspace{3mm}9.2  $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
10.  $res \leftarrow 1$ \\
\\
Start Sliding Window. \\
11.  $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
12.  Loop \\
\hspace{3mm}12.1  $bitcnt \leftarrow bitcnt - 1$ \\
\hspace{3mm}12.2  If $bitcnt = 0$ then do \\
\hspace{6mm}12.2.1  If $digidx = -1$ goto step 13. \\
\hspace{6mm}12.2.2  $buf \leftarrow x_{digidx}$ \\
\hspace{6mm}12.2.3  $digidx \leftarrow digidx - 1$ \\
\hspace{6mm}12.2.4  $bitcnt \leftarrow lg(\beta)$ \\
Continued on next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
\hspace{3mm}12.3  $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
\hspace{3mm}12.4  $buf \leftarrow buf << 1$ \\
\hspace{3mm}12.5  if $mode = 0$ and $y = 0$ then goto step 12. \\
\hspace{3mm}12.6  if $mode = 1$ and $y = 0$ then do \\
\hspace{6mm}12.6.1  $res \leftarrow res^2$ \\
\hspace{6mm}12.6.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.6.3  Goto step 12. \\
\hspace{3mm}12.7  $bitcpy \leftarrow bitcpy + 1$ \\
\hspace{3mm}12.8  $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
\hspace{3mm}12.9  $mode \leftarrow 2$ \\
\hspace{3mm}12.10  If $bitcpy = winsize$ then do \\
\hspace{6mm}Window is full so perform the squarings and single multiplication. \\
\hspace{6mm}12.10.1  for $ix$ from $0$ to $winsize -1$ do \\
\hspace{9mm}12.10.1.1  $res \leftarrow res^2$ \\
\hspace{9mm}12.10.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.10.2  $res \leftarrow res \cdot M_{bitbuf}$ \\
\hspace{6mm}12.10.3  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}Reset the window. \\
\hspace{6mm}12.10.4  $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
\\
No more windows left.  Check for residual bits of exponent. \\
13.  If $mode = 2$ and $bitcpy > 0$ then do \\
\hspace{3mm}13.1  for $ix$ form $0$ to $bitcpy - 1$ do \\
\hspace{6mm}13.1.1  $res \leftarrow res^2$ \\
\hspace{6mm}13.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}13.1.3  $bitbuf \leftarrow bitbuf << 1$ \\
\hspace{6mm}13.1.4  If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
\hspace{9mm}13.1.4.1  $res \leftarrow res \cdot M_{1}$ \\
\hspace{9mm}13.1.4.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
14.  $y \leftarrow res$ \\
15.  Clear $res$, $mu$ and the $M$ array. \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod (continued)}
\end{figure}

\textbf{Algorithm s\_mp\_exptmod.}
This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$.  It takes advantage of the Barrett reduction
algorithm to keep the product small throughout the algorithm.

The first two steps determine the optimal window size based on the number of bits in the exponent.  The larger the exponent the 
larger the window size becomes.  After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated.  This
table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.  

After the table is allocated the first power of $g$ is found.  Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
the rest of the algorithm more efficient.  The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
times.  The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.

Now that the table is available the sliding window may begin.  The following list describes the functions of all the variables in the window.
\begin{enumerate}
\item The variable $mode$ dictates how the bits of the exponent are interpreted.  
\begin{enumerate}
   \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet.  For example, if the exponent were simply 
         $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit.  In this case bits are ignored until a non-zero bit is found.  
   \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet.  In this mode leading $0$ bits 
         are read and a single squaring is performed.  If a non-zero bit is read a new window is created.  
   \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
         downwards.
\end{enumerate}
\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read.  When it reaches zero a new digit
      is fetched from the exponent.
\item The variable $buf$ holds the currently read digit of the exponent. 
\item The variable $digidx$ is an index into the exponents digits.  It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
\item The variable $bitcpy$ indicates how many bits are in the currently formed window.  When it reaches $winsize$ the window is flushed and
      the appropriate operations performed.
\item The variable $bitbuf$ holds the current bits of the window being formed.  
\end{enumerate}

All of step 12 is the window processing loop.  It will iterate while there are digits available form the exponent to read.  The first step
inside this loop is to extract a new digit if no more bits are available in the current digit.  If there are no bits left a new digit is
read and if there are no digits left than the loop terminates.  

After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
upwards.  In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to 
trailing edges the entire exponent is read from most significant bit to least significant bit.

At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read.  This prevents the 
algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read.  Step 12.6 and 12.7-10 handle
the two cases of $mode = 1$ and $mode = 2$ respectively.  

\begin{center}
\begin{figure}[here]
\includegraphics{pics/expt_state.ps}
\caption{Sliding Window State Diagram}
\label{pic:expt_state}
\end{figure}
\end{center}

By step 13 there are no more digits left in the exponent.  However, there may be partial bits in the window left.  If $mode = 2$ then 
a Left-to-Right algorithm is used to process the remaining few bits.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Lines 32 through 46 determine the optimal window size based on the length of the exponent in bits.  The window divisions are sorted
from smallest to greatest so that in each \textbf{if} statement only one condition must be tested.  For example, by the \textbf{if} statement 
on line 38 the value of $x$ is already known to be greater than $140$.  

The conditional piece of code beginning on line 48 allows the window size to be restricted to five bits.  This logic is used to ensure
the table of precomputed powers of $G$ remains relatively small.  

The for loop on line 61 initializes the $M$ array while lines 72 and 77 through 86 initialize the reduction
function that will be used for this modulus.

-- More later.

\section{Quick Power of Two}
Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms.  Recall that a logical shift left $m << k$ is
equivalent to $m \cdot 2^k$.  By this logic when $m = 1$ a quick power of two can be achieved.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_2expt}. \\
\textbf{Input}.   integer $b$ \\
\textbf{Output}.  $a \leftarrow 2^b$ \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
3.  $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
4.  $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_2expt}
\end{figure}

\textbf{Algorithm mp\_2expt.}

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\chapter{Higher Level Algorithms}

This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package.  These
routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.  

The first section describes a method of integer division with remainder that is universally well known.  It provides the signed division logic
for the package.  The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.  
These algorithms serve mostly to simplify other algorithms where small constants are required.  The last two sections discuss how to manipulate 
various representations of integers.  For example, converting from an mp\_int to a string of character.

\section{Integer Division with Remainder}
\label{sec:division}

Integer division aside from modular exponentiation is the most intensive algorithm to compute.  Like addition, subtraction and multiplication
the basis of this algorithm is the long-hand division algorithm taught to school children.  Throughout this discussion several common variables
will be used.  Let $x$ represent the divisor and $y$ represent the dividend.  Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and 
let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$.  The following simple algorithm will be used to start the discussion.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
\textbf{Input}.   integer $x$ and $y$ \\
\textbf{Output}.  $q = \lfloor y/x\rfloor, r = y - xq$ \\
\hline \\
1.  $q \leftarrow 0$ \\
2.  $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
3.  for $t$ from $n$ down to $0$ do \\
\hspace{3mm}3.1  Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
\hspace{3mm}3.2  $q \leftarrow q + k\beta^t$ \\
\hspace{3mm}3.3  $y \leftarrow y - kx\beta^t$ \\
4.  $r \leftarrow y$ \\
5.  Return($q, r$) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Radix-$\beta$ Integer Division}
\label{fig:raddiv}
\end{figure}

As children we are taught this very simple algorithm for the case of $\beta = 10$.  Almost instinctively several optimizations are taught for which
their reason of existing are never explained.  For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.

To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and 
simultaneously $(k + 1)x\beta^t$ is greater than $y$.  Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have.  The habitual method
used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient.  By only using leading
digits a much simpler division may be used to form an educated guess at what the value must be.  In this case $k = \lfloor 54/23\rfloor = 2$ quickly 
arises as a possible  solution.  Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.  
As a  result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.

Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder 
$y = 841 - 3x\beta = 181$.  Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
remainder $y = 181 - 7x = 20$.  The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since 
$237 \cdot 23 + 20 = 5471$ is true.  

\subsection{Quotient Estimation}
\label{sec:divest}
As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend.  When $p$ leading
digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows.  Technically
speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
dividend and divisor are zero.  

The value of the estimation may off by a few values in either direction and in general is fairly correct.  A simplification \cite[pp. 271]{TAOCPV2}
of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$.  The estimate 
using this technique is never too small.  For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ 
represent the most significant digits of the dividend and divisor respectively.

\textbf{Proof.}\textit{  The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to 
$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger.  For all other 
cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$.  The latter portion of the inequalility
$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values.  Next a series of 
inequalities will prove the hypothesis.

\begin{equation}
y - \hat k x \le y - \hat k x_s\beta^s
\end{equation}

This is trivially true since $x \ge x_s\beta^s$.  Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.  

\begin{equation}
y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
\end{equation}

By simplifying the previous inequality the following inequality is formed.

\begin{equation}
y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
\end{equation}

Subsequently,

\begin{equation}
y_{t-2}\beta^{t-2} + \ldots +  y_0  + x_s\beta^s - \beta^s < x_s\beta^s \le x
\end{equation}

Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof.  \textbf{QED}


\subsection{Normalized Integers}
For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$.  By multiplying both
$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
remainder.  The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
lie in the domain of a single digit.  Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.  

\begin{equation} 
{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} 
\end{equation}

At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.  

\subsection{Radix-$\beta$ Division with Remainder}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div}. \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
1.  If $b = 0$ return(\textit{MP\_VAL}). \\
2.  If $\vert a \vert < \vert b \vert$ then do \\
\hspace{3mm}2.1  $d \leftarrow a$ \\
\hspace{3mm}2.2  $c \leftarrow 0$ \\
\hspace{3mm}2.3  Return(\textit{MP\_OKAY}). \\
\\
Setup the quotient to receive the digits. \\
3.  Grow $q$ to $a.used + 2$ digits. \\
4.  $q \leftarrow 0$ \\
5.  $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
6.  $sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = b.sign \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\\
Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
7.  $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
8.  $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
\\
Find the leading digit of the quotient. \\
9.  $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
10.  $y \leftarrow y \cdot \beta^{n - t}$ \\
11.  While ($x \ge y$) do \\
\hspace{3mm}11.1  $q_{n - t} \leftarrow q_{n - t} + 1$ \\
\hspace{3mm}11.2  $x \leftarrow x - y$ \\
12.  $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
\\
Continued on the next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div} (continued). \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
Now find the remainder fo the digits. \\
13.  for $i$ from $n$ down to $(t + 1)$ do \\
\hspace{3mm}13.1  If $i > x.used$ then jump to the next iteration of this loop. \\
\hspace{3mm}13.2  If $x_{i} = y_{t}$ then \\
\hspace{6mm}13.2.1  $q_{i - t - 1} \leftarrow \beta - 1$ \\
\hspace{3mm}13.3  else \\
\hspace{6mm}13.3.1  $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
\hspace{6mm}13.3.2  $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
\hspace{6mm}13.3.3  $q_{i - t - 1} \leftarrow \hat r$ \\
\hspace{3mm}13.4  $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
\\
Fixup quotient estimation. \\
\hspace{3mm}13.5  Loop \\
\hspace{6mm}13.5.1  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\hspace{6mm}13.5.2  t$1 \leftarrow 0$ \\
\hspace{6mm}13.5.3  t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
\hspace{6mm}13.5.4  $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
\hspace{6mm}13.5.5  t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
\hspace{6mm}13.5.6  If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
\hspace{3mm}13.6  t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
\hspace{3mm}13.7  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{3mm}13.8  $x \leftarrow x - $ t$1$ \\
\hspace{3mm}13.9  If $x.sign = MP\_NEG$ then \\
\hspace{6mm}13.10  t$1 \leftarrow y$ \\
\hspace{6mm}13.11  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{6mm}13.12  $x \leftarrow x + $ t$1$ \\
\hspace{6mm}13.13  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\\
Finalize the result. \\
14.  Clamp excess digits of $q$ \\
15.  $c \leftarrow q, c.sign \leftarrow sign$ \\
16.  $x.sign \leftarrow a.sign$ \\
17.  $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
18.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div (continued)}
\end{figure}
\textbf{Algorithm mp\_div.}
This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor.  The algorithm is a signed
division and will produce a fully qualified quotient and remainder.

First the divisor $b$ must be non-zero which is enforced in step one.  If the divisor is larger than the dividend than the quotient is implicitly 
zero and the remainder is the dividend.  

After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient.  Two unsigned copies of the
divisor $y$ and dividend $x$ are made as well.  The core of the division algorithm is an unsigned division and will only work if the values are
positive.  Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.  
This is performed by shifting both to the left by enough bits to get the desired normalization.  

At this point the division algorithm can begin producing digits of the quotient.  Recall that maximum value of the estimation used is 
$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means.  In this case $y$ is shifted
to the left (\textit{step ten}) so that it has the same number of digits as $x$.  The loop on step eleven will subtract multiples of the 
shifted copy of $y$ until $x$ is smaller.  Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
times to produce the desired leading digit of the quotient.  

Now the remainder of the digits can be produced.  The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
accurately approximate the true quotient digit.  The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.  

Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high.  The next step of the estimation process is
to refine the estimation.  The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
order approximation to adjust the quotient digit.

After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
by optimizing Barrett reduction.}.  Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.  

Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the 
remainder.  An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie 
outside their respective boundaries.  For example, if $t = 0$ or $i \le 1$ then the digits would be undefined.  In those cases the digits should
respectively be replaced with a zero.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_div.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The implementation of this algorithm differs slightly from the pseudo code presented previously.  In this algorithm either of the quotient $c$ or
remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired.  For example, the C code to call the division
algorithm with only the quotient is 

\begin{verbatim}
mp_div(&a, &b, &c, NULL);  /* c = [a/b] */
\end{verbatim}

Lines 109 and 113 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor 
respectively.  After the two trivial cases all of the temporary variables are initialized.  Line 148 determines the sign of 
the quotient and line 148 ensures that both $x$ and $y$ are positive.  

The number of bits in the leading digit is calculated on line 151.  Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
of precision which when reduced modulo $lg(\beta)$ produces the value of $k$.  In this case $k$ is the number of bits in the leading digit which is
exactly what is required.  For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
them to the left by $lg(\beta) - 1 - k$ bits.

Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively.  These are first used to produce the 
leading digit of the quotient.  The loop beginning on line 184 will produce the remainder of the quotient digits.

The conditional ``continue'' on line 187 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
algorithm eliminates multiple non-zero digits in a single iteration.  This ensures that $x_i$ is always non-zero since by definition the digits
above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.  

Lines 214, 216 and 223 through 225 manually construct the high accuracy estimations by setting the digits of the two mp\_int 
variables directly.  

\section{Single Digit Helpers}

This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants.  All of 
the helper functions assume the single digit input is positive and will treat them as such.

\subsection{Single Digit Addition and Subtraction}

Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction 
algorithms.   As a result these algorithms are subtantially simpler with a slight cost in performance.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = a + b$ \\
\hline \\
1.  $t \leftarrow b$ (\textit{mp\_set}) \\
2.  $c \leftarrow a + t$ \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_add\_d}
\end{figure}

\textbf{Algorithm mp\_add\_d.}
This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Clever use of the letter 't'.

\subsubsection{Subtraction}
The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.

\subsection{Single Digit Multiplication}
Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
multiplication algorithm.  Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
only has one digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = ab$ \\
\hline \\
1.  $pa \leftarrow a.used$ \\
2.  Grow $c$ to at least $pa + 1$ digits. \\
3.  $oldused \leftarrow c.used$ \\
4.  $c.used \leftarrow pa + 1$ \\
5.  $c.sign \leftarrow a.sign$ \\
6.  $\mu \leftarrow 0$ \\
7.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}7.1  $\hat r \leftarrow \mu + a_{ix}b$ \\
\hspace{3mm}7.2  $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}7.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
8.  $c_{pa} \leftarrow \mu$ \\
9.  for $ix$ from $pa + 1$ to $oldused$ do \\
\hspace{3mm}9.1  $c_{ix} \leftarrow 0$ \\
10.  Clamp excess digits of $c$. \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_d}
\end{figure}
\textbf{Algorithm mp\_mul\_d.}
This algorithm quickly multiplies an mp\_int by a small single digit value.  It is specially tailored to the job and has a minimal of overhead.  
Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is 
read from the source.  This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.  

\subsection{Single Digit Division}
Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion.  Since the
divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = \lfloor a / b \rfloor, d = a - cb$ \\
\hline \\
1.  If $b = 0$ then return(\textit{MP\_VAL}).\\
2.  If $b = 3$ then use algorithm mp\_div\_3 instead. \\
3.  Init $q$ to $a.used$ digits.  \\
4.  $q.used \leftarrow a.used$ \\
5.  $q.sign \leftarrow a.sign$ \\
6.  $\hat w \leftarrow 0$ \\
7.  for $ix$ from $a.used - 1$ down to $0$ do \\
\hspace{3mm}7.1  $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
\hspace{3mm}7.2  If $\hat w \ge b$ then \\
\hspace{6mm}7.2.1  $t \leftarrow \lfloor \hat w / b \rfloor$ \\
\hspace{6mm}7.2.2  $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}7.3  else\\
\hspace{6mm}7.3.1  $t \leftarrow 0$ \\
\hspace{3mm}7.4  $q_{ix} \leftarrow t$ \\
8.  $d \leftarrow \hat w$ \\
9.  Clamp excess digits of $q$. \\
10.  $c \leftarrow q$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_d}
\end{figure}
\textbf{Algorithm mp\_div\_d.}
This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach.  Essentially in every iteration of the
algorithm another digit of the dividend is reduced and another digit of quotient produced.  Provided $b < \beta$ the value of $\hat w$
after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.  

If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3.  It replaces the division by three with
a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup.  In essence it is much like the Barrett reduction
from chapter seven.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
indicate the respective value is not required.  This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.

The division and remainder on lines 44 and @45,%@ can be replaced often by a single division on most processors.  For example, the 32-bit x86 based 
processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously.  Unfortunately the GCC 
compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.  

\subsection{Single Digit Root Extraction}

Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned.  Algorithms such as the Newton-Raphson approximation 
(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.  

\begin{equation}
x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
\label{eqn:newton}
\end{equation}

In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired.  The derivative of $f(x)$ is 
simply $f'(x) = nx^{n - 1}$.  Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
such as the real numbers.  As a result the root found can be above the true root by few and must be manually adjusted.  Ideally at the end of the 
algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_n\_root}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c^b \le a$ \\
\hline \\
1.  If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  $sign \leftarrow a.sign$ \\
3.  $a.sign \leftarrow MP\_ZPOS$ \\
4.  t$2 \leftarrow 2$ \\
5.  Loop \\
\hspace{3mm}5.1  t$1 \leftarrow $ t$2$ \\
\hspace{3mm}5.2  t$3 \leftarrow $ t$1^{b - 1}$ \\
\hspace{3mm}5.3  t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
\hspace{3mm}5.4  t$2 \leftarrow $ t$2 - a$ \\
\hspace{3mm}5.5  t$3 \leftarrow $ t$3 \cdot b$ \\
\hspace{3mm}5.6  t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
\hspace{3mm}5.7  t$2 \leftarrow $ t$1 - $ t$3$ \\
\hspace{3mm}5.8  If t$1 \ne $ t$2$ then goto step 5.  \\
6.  Loop \\
\hspace{3mm}6.1  t$2 \leftarrow $ t$1^b$ \\
\hspace{3mm}6.2  If t$2 > a$ then \\
\hspace{6mm}6.2.1  t$1 \leftarrow $ t$1 - 1$ \\
\hspace{6mm}6.2.2  Goto step 6. \\
7.  $a.sign \leftarrow sign$ \\
8.  $c \leftarrow $ t$1$ \\
9.  $c.sign \leftarrow sign$  \\
10.  Return(\textit{MP\_OKAY}).  \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_n\_root}
\end{figure}
\textbf{Algorithm mp\_n\_root.}
This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach.  It is partially optimized based on the observation
that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator.  That is at first the denominator is calculated by finding
$x^{b - 1}$.  This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator.  This saves a total of $b - 1$ 
multiplications by t$1$ inside the loop.  

The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
root.  Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\section{Random Number Generation}

Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms.  Pollard-Rho 
factoring for example, can make use of random values as starting points to find factors of a composite integer.  In this case the algorithm presented
is solely for simulations and not intended for cryptographic use.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rand}. \\
\textbf{Input}.   An integer $b$ \\
\textbf{Output}.  A pseudo-random number of $b$ digits \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $b \le 0$ return(\textit{MP\_OKAY}) \\
3.  Pick a non-zero random digit $d$. \\
4.  $a \leftarrow a + d$ \\
5.  for $ix$ from 1 to $d - 1$ do \\
\hspace{3mm}5.1  $a \leftarrow a \cdot \beta$ \\
\hspace{3mm}5.2  Pick a random digit $d$. \\
\hspace{3mm}5.3  $a \leftarrow a + d$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rand}
\end{figure}
\textbf{Algorithm mp\_rand.}
This algorithm produces a pseudo-random integer of $b$ digits.  By ensuring that the first digit is non-zero the algorithm also guarantees that the
final result has at least $b$ digits.  It relies heavily on a third-part random number generator which should ideally generate uniformly all of
the integers from $0$ to $\beta - 1$.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\section{Formatted Representations}
The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties.  For example, the ability to
be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
into a program.

\subsection{Reading Radix-n Input}
For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to 
printable characters.  For example, when the character ``N'' is read it represents the integer $23$.  The first $16$ characters of the
map are for the common representations up to hexadecimal.  After that they match the ``base64'' encoding scheme which are suitable chosen
such that they are printable.  While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
mediums.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{cc|cc|cc|cc}
\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} &  \textbf{Value} & \textbf{Char} \\
\hline 
0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
8 & 8 & 9 & 9 & 10 & A & 11 & B \\
12 & C & 13 & D & 14 & E & 15 & F \\
16 & G & 17 & H & 18 & I & 19 & J \\
20 & K & 21 & L & 22 & M & 23 & N \\
24 & O & 25 & P & 26 & Q & 27 & R \\
28 & S & 29 & T & 30 & U & 31 & V \\
32 & W & 33 & X & 34 & Y & 35 & Z \\
36 & a & 37 & b & 38 & c & 39 & d \\
40 & e & 41 & f & 42 & g & 43 & h \\
44 & i & 45 & j & 46 & k & 47 & l \\
48 & m & 49 & n & 50 & o & 51 & p \\
52 & q & 53 & r & 54 & s & 55 & t \\
56 & u & 57 & v & 58 & w & 59 & x \\
60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
\hline
\end{tabular}
\end{center}
\caption{Lower ASCII Map}
\label{fig:ASC}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_read\_radix}. \\
\textbf{Input}.   A string $str$ of length $sn$ and radix $r$. \\
\textbf{Output}.  The radix-$\beta$ equivalent mp\_int. \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  $ix \leftarrow 0$ \\
3.  If $str_0 =$ ``-'' then do \\
\hspace{3mm}3.1  $ix \leftarrow ix + 1$ \\
\hspace{3mm}3.2  $sign \leftarrow MP\_NEG$ \\
4.  else \\
\hspace{3mm}4.1  $sign \leftarrow MP\_ZPOS$ \\
5.  $a \leftarrow 0$ \\
6.  for $iy$ from $ix$ to $sn - 1$ do \\
\hspace{3mm}6.1  Let $y$ denote the position in the map of $str_{iy}$. \\
\hspace{3mm}6.2  If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
\hspace{3mm}6.3  $a \leftarrow a \cdot r$ \\
\hspace{3mm}6.4  $a \leftarrow a + y$ \\
7.  If $a \ne 0$ then $a.sign \leftarrow sign$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_read\_radix}
\end{figure}
\textbf{Algorithm mp\_read\_radix.}
This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer.  A minus symbol ``-'' may precede the 
string  to indicate the value is negative, otherwise it is assumed to be positive.  The algorithm will read up to $sn$ characters from the input
and will stop when it reads a character it cannot map the algorithm stops reading characters from the string.  This allows numbers to be embedded
as part of larger input without any significant problem.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsection{Generating Radix-$n$ Output}
Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toradix}. \\
\textbf{Input}.   A mp\_int $a$ and an integer $r$\\
\textbf{Output}.  The radix-$r$ representation of $a$ \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}).  \\
3.  $t \leftarrow a$ \\
4.  $str \leftarrow$ ``'' \\
5.  if $t.sign = MP\_NEG$ then \\
\hspace{3mm}5.1  $str \leftarrow str + $ ``-'' \\
\hspace{3mm}5.2  $t.sign = MP\_ZPOS$ \\
6.  While ($t \ne 0$) do \\
\hspace{3mm}6.1  $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
\hspace{3mm}6.2  $t \leftarrow \lfloor t / r \rfloor$ \\
\hspace{3mm}6.3  Look up $d$ in the map and store the equivalent character in $y$. \\
\hspace{3mm}6.4  $str \leftarrow str + y$ \\
7.  If $str_0 = $``$-$'' then \\
\hspace{3mm}7.1  Reverse the digits $str_1, str_2, \ldots str_n$. \\
8.  Otherwise \\
\hspace{3mm}8.1  Reverse the digits $str_0, str_1, \ldots str_n$. \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toradix}
\end{figure}
\textbf{Algorithm mp\_toradix.}
This algorithm computes the radix-$r$ representation of an mp\_int $a$.  The ``digits'' of the representation are extracted by reducing 
successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$.  Note that instead of actually dividing by $r^k$ in
each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration.  As a result a series of trivial $n \times 1$ divisions
are required instead of a series of $n \times k$ divisions.  One design flaw of this approach is that the digits are produced in the reverse order 
(see~\ref{fig:mpradix}).  To remedy this flaw the digits must be swapped or simply ``reversed''.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
\hline $1234$ & -- & -- \\
\hline $123$  & $4$ & ``4'' \\
\hline $12$   & $3$ & ``43'' \\
\hline $1$    & $2$ & ``432'' \\
\hline $0$    & $1$ & ``4321'' \\
\hline
\end{tabular}
\end{center}
\caption{Example of Algorithm mp\_toradix.}
\label{fig:mpradix}
\end{figure}

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\chapter{Number Theoretic Algorithms}
This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi 
symbol computation.  These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
various Sieve based factoring algorithms.

\section{Greatest Common Divisor}
The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
both $a$ and $b$.  That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
simultaneously.

The most common approach (cite) is to reduce one input modulo another.  That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
$r$ is also divisible by $k$.  The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}1.2  $a \leftarrow b$ \\
\hspace{3mm}1.3  $b \leftarrow r$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (I)}
\label{fig:gcd1}
\end{figure}

This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly.  However, divisions are
relatively expensive operations to perform and should ideally be avoided.  There is another approach based on a similar relationship of 
greatest common divisors.  The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.  
In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}1.2  $b \leftarrow b - a$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (II)}
\label{fig:gcd2}
\end{figure}

\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$.  In other
words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$.  Since both $a$ and $b$ are always 
divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the 
second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof.  \textbf{QED}.

As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful.  Specially if $b$ is much larger than $a$ such that 
$b - a$ is still very much larger than $a$.  A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
not divide the greatest common divisor but will divide $b - a$.  In this case ${b - a} \over p$ is also an integer and still divisible by
the greatest common divisor.

However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.  
Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  $k \leftarrow 0$ \\
2.  While $a$ and $b$ are both divisible by $p$ do \\
\hspace{3mm}2.1  $a \leftarrow \lfloor a / p \rfloor$ \\
\hspace{3mm}2.2  $b \leftarrow \lfloor b / p \rfloor$ \\
\hspace{3mm}2.3  $k \leftarrow k + 1$ \\
3.  While $a$ is divisible by $p$ do \\
\hspace{3mm}3.1  $a \leftarrow \lfloor a / p \rfloor$ \\
4.  While $b$ is divisible by $p$ do \\
\hspace{3mm}4.1  $b \leftarrow \lfloor b / p \rfloor$ \\
5.  While ($b > 0$) do \\
\hspace{3mm}5.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}5.2  $b \leftarrow b - a$ \\
\hspace{3mm}5.3  While $b$ is divisible by $p$ do \\
\hspace{6mm}5.3.1  $b \leftarrow \lfloor b / p \rfloor$ \\
6.  Return($a \cdot p^k$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (III)}
\label{fig:gcd3}
\end{figure}

This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ 
decreases more rapidly.  The first loop on step two removes powers of $p$ that are in common.  A count, $k$, is kept which will present a common
divisor of $p^k$.  After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$.  This means that $p$ can be safely 
divided out of the difference $b - a$ so long as the division leaves no remainder.  

In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often.  It also helps that division by $p$ be easy
to compute.  The ideal choice of $p$ is two since division by two amounts to a right logical shift.  Another important observation is that by
step five both $a$ and $b$ are odd.  Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the 
largest of the pair.

\subsection{Complete Greatest Common Divisor}
The algorithms presented so far cannot handle inputs which are zero or negative.  The following algorithm can handle all input cases properly
and will produce the greatest common divisor.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_gcd}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The greatest common divisor $c = (a, b)$.  \\
\hline \\
1.  If $a = 0$ then \\
\hspace{3mm}1.1  $c \leftarrow \vert b \vert $ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $b = 0$ then \\
\hspace{3mm}2.1  $c \leftarrow \vert a \vert $ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
4.  $k \leftarrow 0$ \\
5.  While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}5.1  $k \leftarrow k + 1$ \\
\hspace{3mm}5.2  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}5.3  $v \leftarrow \lfloor v / 2 \rfloor$ \\
6.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
7.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
8.  While $v.used > 0$ \\
\hspace{3mm}8.1  If $\vert u \vert > \vert v \vert$ then \\
\hspace{6mm}8.1.1  Swap $u$ and $v$. \\
\hspace{3mm}8.2  $v \leftarrow \vert v \vert - \vert u \vert$ \\
\hspace{3mm}8.3  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{6mm}8.3.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
9.  $c \leftarrow u \cdot 2^k$ \\
10.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_gcd}
\end{figure}
\textbf{Algorithm mp\_gcd.}
This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$.  The algorithm was originally based on Algorithm B of
Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain.  In theory it achieves the same asymptotic working time as
Algorithm B and in practice this appears to be true.  

The first two steps handle the cases where either one of or both inputs are zero.  If either input is zero the greatest common divisor is the 
largest input or zero if they are both zero.  If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of 
$a$ and $b$ respectively and the algorithm will proceed to reduce the pair.

Step five will divide out any common factors of two and keep track of the count in the variable $k$.  After this step, two is no longer a
factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even.  Step 
six and seven ensure that the $u$ and $v$ respectively have no more factors of two.  At most only one of the while--loops will iterate since 
they cannot both be even.

By step eight both of $u$ and $v$ are odd which is required for the inner logic.  First the pair are swapped such that $v$ is equal to
or greater than $u$.  This ensures that the subtraction on step 8.2 will always produce a positive and even result.  Step 8.3 removes any
factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.

After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six.  The result
must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

This function makes use of the macros mp\_iszero and mp\_iseven.  The former evaluates to $1$ if the input mp\_int is equivalent to the 
integer zero otherwise it evaluates to $0$.  The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
it evaluates to $0$.  Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero.  The three 
trivial cases of inputs are handled on lines 24 through 30.  After those lines the inputs are assumed to be non-zero.

Lines 32 and 37 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively.  At this point the common factors of two 
must be divided out of the two inputs.  The block starting at line 44 removes common factors of two by first counting the number of trailing
zero bits in both.  The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values.  It is assumed that 
the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than 
entries than are accessible by an ``int'' so this is not a limitation.}.  

At this point there are no more common factors of two in the two values.  The divisions by a power of two on lines 62 and 68 remove 
any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm.  The while loop
on line 73 performs the reduction of the pair until $v$ is equal to zero.  The unsigned comparison and subtraction algorithms are used in
place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.

\section{Least Common Multiple}
The least common multiple of a pair of integers is their product divided by their greatest common divisor.  For two integers $a$ and $b$ the
least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$.  For example, if $a = 2 \cdot 2 \cdot 3 = 12$
and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.

The least common multiple arises often in coding theory as well as number theory.  If two functions have periods of $a$ and $b$ respectively they will
collide, that is be in synchronous states, after only $[ a, b ]$ iterations.  This is why, for example, random number generators based on 
Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).  
Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lcm}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The least common multiple $c = [a, b]$.  \\
\hline \\
1.  $c \leftarrow (a, b)$ \\
2.  $t \leftarrow a \cdot b$ \\
3.  $c \leftarrow \lfloor t / c \rfloor$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lcm}
\end{figure}
\textbf{Algorithm mp\_lcm.}
This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$.  It computes the least common multiple directly by
dividing the product of the two inputs by their greatest common divisor.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\section{Jacobi Symbol Computation}
To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg.  What is the name of this?} off which the Jacobi symbol is 
defined.  The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$.  Numerically it is
equivalent to equation \ref{eqn:legendre}.

\textit{-- Tom, don't be an ass, cite your source here...!}

\begin{equation}
a^{(p-1)/2} \equiv \begin{array}{rl}
                              -1 &  \mbox{if }a\mbox{ is a quadratic non-residue.} \\
                              0  &  \mbox{if }a\mbox{ divides }p\mbox{.} \\
                              1  &  \mbox{if }a\mbox{ is a quadratic residue}. 
                              \end{array} \mbox{ (mod }p\mbox{)}
\label{eqn:legendre}                              
\end{equation}

\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
An integer $a$ is a quadratic residue if the following equation has a solution.

\begin{equation}
x^2 \equiv a \mbox{ (mod }p\mbox{)}
\label{eqn:root}
\end{equation}

Consider the following equation.

\begin{equation}
0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
\label{eqn:rooti}
\end{equation}

Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true.  If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
then the quantity in the braces must be zero.  By reduction,

\begin{eqnarray}
\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0  \nonumber \\
\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
x^2 \equiv a \mbox{ (mod }p\mbox{)} 
\end{eqnarray}

As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue.  If $a$ does not divide $p$ and $a$
is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
\begin{equation}
0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
\end{equation}
One of the terms on the right hand side must be zero.  \textbf{QED}

\subsection{Jacobi Symbol}
The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2.  If $p = \prod_{i=0}^n p_i$ then
the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.

\begin{equation}
\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
\end{equation}

By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function.  The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
further details.} will be used to derive an efficient Jacobi symbol algorithm.  Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
following are true.  

\begin{enumerate}
\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. 
\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$.  Otherwise, it equals $-1$.
\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$.  More specifically 
$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.  
\end{enumerate}

Using these facts if $a = 2^k \cdot a'$ then

\begin{eqnarray}
\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
                               = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) 
\label{eqn:jacobi}
\end{eqnarray}

By fact five, 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.

\begin{equation}
\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right )  \cdot (-1)^{(p-1)(a'-1)/4} 
\end{equation}

The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively.  The value of 
$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$.  Using this approach the 
factors of $p$ do not have to be known.  Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the 
Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_jacobi}. \\
\textbf{Input}.   mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
\textbf{Output}.  The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
\hline \\
1.  If $a = 0$ then \\
\hspace{3mm}1.1  $c \leftarrow 0$ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $a = 1$ then \\
\hspace{3mm}2.1  $c \leftarrow 1$ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  $a' \leftarrow a$ \\
4.  $k \leftarrow 0$ \\
5.  While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}5.1  $k \leftarrow k + 1$ \\
\hspace{3mm}5.2  $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
6.  If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
\hspace{3mm}6.1  $s \leftarrow 1$ \\
7.  else \\
\hspace{3mm}7.1  $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
\hspace{3mm}7.2  If $r = 1$ or $r = 7$ then \\
\hspace{6mm}7.2.1  $s \leftarrow 1$ \\
\hspace{3mm}7.3  else \\
\hspace{6mm}7.3.1  $s \leftarrow -1$ \\
8.  If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
\hspace{3mm}8.1  $s \leftarrow -s$ \\
9.  If $a' \ne 1$ then \\
\hspace{3mm}9.1  $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
\hspace{3mm}9.2  $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
10.  $c \leftarrow s$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_jacobi}
\end{figure}
\textbf{Algorithm mp\_jacobi.}
This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three.  The algorithm
is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.  

Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively.  Step five determines the number of two factors in the
input $a$.  If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one.  If $k$ is odd than the term evaluates to one 
if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled 
the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$.  The latter term evaluates to one if both $p$ and $a'$ 
are congruent to one modulo four, otherwise it evaluates to negative one.

By step nine if $a'$ does not equal one a recursion is required.  Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C 
variable name character. 

The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm.  If the input is non-trivial the algorithm
has to proceed compute the Jacobi.  The variable $s$ is used to hold the current Jacobi product.  Note that $s$ is merely a C ``int'' data type since
the values it may obtain are merely $-1$, $0$ and $1$.  

After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$.  Technically only the least significant
bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same 
processor requirements and neither is faster than the other.

Line 58 through 71 determines the value of $\left ( { 2 \over p } \right )^k$.  If the least significant bit of $k$ is zero than
$k$ is even and the value is one.  Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight.  The value of
$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 71 through 74.  

Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.  

\textit{-- Comment about default $s$ and such...}

\section{Modular Inverse}
\label{sec:modinv}
The modular inverse of a number actually refers to the modular multiplicative inverse.  Essentially for any integer $a$ such that $(a, p) = 1$ there
exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$.  The integer $b$ is called the multiplicative inverse of $a$ which is
denoted as $b = a^{-1}$.  Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and 
fields of integers.  However, the former will be the matter of discussion.

The simplest approach is to compute the algebraic inverse of the input.  That is to compute $b \equiv a^{\Phi(p) - 1}$.  If $\Phi(p)$ is the 
order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$.  The proof of which is trivial.

\begin{equation}
ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
\end{equation}

However, as simple as this approach may be it has two serious flaws.  It requires that the value of $\Phi(p)$ be known which if $p$ is composite 
requires all of the prime factors.  This approach also is very slow as the size of $p$ grows.  

A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear 
Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.

\begin{equation}
ab + pq = 1
\end{equation}

Where $a$, $b$, $p$ and $q$ are all integers.  If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of 
$a$ modulo $p$.  The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.  
However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place.  The
binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine 
equation.  

\subsection{General Case}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_invmod}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$.  \\
\textbf{Output}.  The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_VAL}). \\
2.  If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
3.  $x \leftarrow \vert a \vert, y \leftarrow b$ \\
4.  If $x_0 \equiv y_0  \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
5.  $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
6.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}6.2  If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}6.2.1  $A \leftarrow A + y$ \\
\hspace{6mm}6.2.2  $B \leftarrow B - x$ \\
\hspace{3mm}6.3  $A \leftarrow \lfloor A / 2 \rfloor$ \\
\hspace{3mm}6.4  $B \leftarrow \lfloor B / 2 \rfloor$ \\
7.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
\hspace{3mm}7.2  If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}7.2.1  $C \leftarrow C + y$ \\
\hspace{6mm}7.2.2  $D \leftarrow D - x$ \\
\hspace{3mm}7.3  $C \leftarrow \lfloor C / 2 \rfloor$ \\
\hspace{3mm}7.4  $D \leftarrow \lfloor D / 2 \rfloor$ \\
8.  If $u \ge v$ then \\
\hspace{3mm}8.1  $u \leftarrow u - v$ \\
\hspace{3mm}8.2  $A \leftarrow A - C$ \\
\hspace{3mm}8.3  $B \leftarrow B - D$ \\
9.  else \\
\hspace{3mm}9.1  $v \leftarrow v - u$ \\
\hspace{3mm}9.2  $C \leftarrow C - A$ \\
\hspace{3mm}9.3  $D \leftarrow D - B$ \\
10.  If $u \ne 0$ goto step 6. \\
11.  If $v \ne 1$ return(\textit{MP\_VAL}). \\
12.  While $C \le 0$ do \\
\hspace{3mm}12.1  $C \leftarrow C + b$ \\
13.  While $C \ge b$ do \\
\hspace{3mm}13.1  $C \leftarrow C - b$ \\
14.  $c \leftarrow C$ \\
15.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\end{figure}
\textbf{Algorithm mp\_invmod.}
This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$.  This algorithm is a variation of the 
extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}.  It has been modified to only compute the modular inverse and not a complete
Diophantine solution.  

If $b \le 0$ than the modulus is invalid and MP\_VAL is returned.  Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
inverse for $a$ and the error is reported.  

The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd.  In this case
the other variables to the Diophantine equation are solved.  The algorithm terminates when $u = 0$ in which case the solution is

\begin{equation}
Ca + Db = v
\end{equation}

If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists.  Otherwise, $C$
is the modular inverse of $a$.  The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie 
within $1 \le a^{-1} < b$.  Step numbers twelve and thirteen adjust the inverse until it is in range.  If the original input $a$ is within $0 < a < p$ 
then only a couple of additions or subtractions will be required to adjust the inverse.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsubsection{Odd Moduli}

When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse.  In particular by attempting to solve
the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.  

The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed.  This 
optimization will halve the time required to compute the modular inverse.

\section{Primality Tests}

A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself.  For example, $a = 7$ is prime 
since the integers $2 \ldots 6$ do not evenly divide $a$.  By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. 

Prime numbers arise in cryptography considerably as they allow finite fields to be formed.  The ability to determine whether an integer is prime or
not quickly has been a viable subject in cryptography and number theory for considerable time.  The algorithms that will be presented are all
probablistic algorithms in that when they report an integer is composite it must be composite.  However, when the algorithms report an integer is
prime the algorithm may be incorrect.  

As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as 
well be zero.  For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.

\subsection{Trial Division}

Trial division means to attempt to evenly divide a candidate integer by small prime integers.  If the candidate can be evenly divided it obviously
cannot be prime.  By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime.  However, such a test
would require a prohibitive amount of time as $n$ grows.

Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead.  By performing trial division with only a subset
of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime.  However, often it can prove a candidate is not prime.

The benefit of this test is that trial division by small values is fairly efficient.  Specially compared to the other algorithms that will be
discussed shortly.  The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
$1 - {1.12 \over ln(q)}$.  The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range 
$3 \le q \le 100$.  

At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly.  At $q = 90$ further testing is generally not going to 
be of any practical use.  In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate 
approximately $80\%$ of all candidate integers.  The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base.  The 
array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$.  \\
\hline \\
1.  for $ix$ from $0$ to $PRIME\_SIZE$ do \\
\hspace{3mm}1.1  $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
\hspace{3mm}1.2  If $d = 0$ then \\
\hspace{6mm}1.2.1  $c \leftarrow 1$ \\
\hspace{6mm}1.2.2  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow 0$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_is\_divisible}
\end{figure}
\textbf{Algorithm mp\_prime\_is\_divisible.}
This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

The algorithm defaults to a return of $0$ in case an error occurs.  The values in the prime table are all specified to be in the range of a 
mp\_digit.  The table \_\_prime\_tab is defined in the following file.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

Note that there are two possible tables.  When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
upto $1619$ are used.  Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. 

\subsection{The Fermat Test}
The Fermat test is probably one the oldest tests to have a non-trivial probability of success.  It is based on the fact that if $n$ is in 
fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$.  The reason being that if $n$ is prime than the order of
the multiplicative sub group is $n - 1$.  Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to 
$a^1 = a$.  

If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$.  In which case 
it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$.  However, this test is not absolute as it is possible that the order
of a base will divide $n - 1$ which would then be reported as prime.  Such a base yields what is known as a Fermat pseudo-prime.  Several 
integers known as Carmichael numbers will be a pseudo-prime to all valid bases.  Fortunately such numbers are extremely rare as $n$ grows
in size.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_fermat}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$.  \\
\hline \\
1.  $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
2.  If $t = b$ then \\
\hspace{3mm}2.1  $c = 1$ \\
3.  else \\
\hspace{3mm}3.1  $c = 0$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_fermat}
\end{figure}
\textbf{Algorithm mp\_prime\_fermat.}
This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not.  It uses a single modular exponentiation to
determine the result.  

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}

\subsection{The Miller-Rabin Test}
The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen 
candidate  integers.  The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the 
value must be equal to $-1$.  The squarings are stopped as soon as $-1$ is observed.  If the value of $1$ is observed first it means that
some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$.  \\
\hline
1.  $a' \leftarrow a - 1$ \\
2.  $r  \leftarrow n1$    \\
3.  $c \leftarrow 0, s  \leftarrow 0$ \\
4.  While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}4.1  $s \leftarrow s + 1$ \\
\hspace{3mm}4.2  $r \leftarrow \lfloor r / 2 \rfloor$ \\
5.  $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
6.  If $y \nequiv \pm 1$ then \\
\hspace{3mm}6.1  $j \leftarrow 1$ \\
\hspace{3mm}6.2  While $j \le (s - 1)$ and $y \nequiv a'$ \\
\hspace{6mm}6.2.1  $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
\hspace{6mm}6.2.2  If $y = 1$ then goto step 8. \\
\hspace{6mm}6.2.3  $j \leftarrow j + 1$ \\
\hspace{3mm}6.3  If $y \nequiv a'$ goto step 8. \\
7.  $c \leftarrow 1$\\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_miller\_rabin}
\end{figure}
\textbf{Algorithm mp\_prime\_miller\_rabin.}
This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$.  It will set $c = 1$ if the algorithm cannot determine
if $b$ is composite or $c = 0$ if $b$ is provably composite.  The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.  

If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not.  Otherwise, the algorithm will
square $y$ upto $s - 1$ times stopping only when $y \equiv -1$.  If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
is provably composite.  If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite.  If $a$ is not provably 
composite then it is \textit{probably} prime.

\vspace{+3mm}\begin{small}
\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c
\vspace{-3mm}
\begin{alltt}
\end{alltt}
\end{small}




\backmatter
\appendix
\begin{thebibliography}{ABCDEF}
\bibitem[1]{TAOCPV2}
Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998

\bibitem[2]{HAC}
A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996

\bibitem[3]{ROSE}
Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999

\bibitem[4]{COMBA}
Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)

\bibitem[5]{KARA}
A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294

\bibitem[6]{KARAP}
Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002

\bibitem[7]{BARRETT}
Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.

\bibitem[8]{MONT}
P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.

\bibitem[9]{DRMET}
Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories

\bibitem[10]{MMB}
J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89

\bibitem[11]{RSAREF}
R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}

\bibitem[12]{DHREF}
Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976

\bibitem[13]{IEEE}
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)

\bibitem[14]{GMP}
GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}

\bibitem[15]{MPI}
Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}

\bibitem[16]{OPENSSL}
OpenSSL Cryptographic Toolkit, \url{http://openssl.org}

\bibitem[17]{LIP}
Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}

\bibitem[18]{ISOC}
JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''

\bibitem[19]{JAVA}
The Sun Java Website, \url{http://java.sun.com/}

\end{thebibliography}

\input{tommath.ind}

\end{document}

Changes to libtommath/tommath_superclass.h.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
   #undef  BN_S_MP_EXPTMOD_C
   #undef  BN_MP_DIV_3_C
   #undef  BN_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_MP_INVMOD_C

   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
    * trouble.
    */
   #undef  BN_S_MP_MUL_DIGS_C
   #undef  BN_S_MP_SQR_C
   #undef  BN_MP_MONTGOMERY_REDUCE_C
#endif

#endif







|

|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
   #undef  BN_S_MP_EXPTMOD_C
   #undef  BN_MP_DIV_3_C
   #undef  BN_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_MP_INVMOD_C

   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
    * trouble.  
    */
   #undef  BN_S_MP_MUL_DIGS_C
   #undef  BN_S_MP_SQR_C
   #undef  BN_MP_MONTGOMERY_REDUCE_C
#endif

#endif

Changes to macosx/GNUmakefile.

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
endif
endif
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# keep copy of debug library around, so that
# Deployment build can be installed on top
# of Development build without overwriting
# the debug library
	@if [ -d "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" ]; then \
	    cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}"; \
	    ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"; \
	fi
endif

clean-${PROJECT}: %-${PROJECT}:
	${DO_MAKE}
	rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${TCLSH},tcltest}
	rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \
	rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \







<
|
|
<







176
177
178
179
180
181
182

183
184

185
186
187
188
189
190
191
endif
endif
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# keep copy of debug library around, so that
# Deployment build can be installed on top
# of Development build without overwriting
# the debug library

	@cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \
	ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"

endif

clean-${PROJECT}: %-${PROJECT}:
	${DO_MAKE}
	rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${TCLSH},tcltest}
	rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \
	rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \

Changes to macosx/README.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
	http://groups.google.com/group/comp.lang.tcl/

- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on Mac OS X, see
	http://wiki.tcl.tk/_/ref?N=3753
	http://wiki.tcl.tk/_/ref?N=8361

- Please report bugs with Tcl on Mac OS X to the tracker:
	https://core.tcl-lang.org/tcl/reportlist

2. Using Tcl on Mac OS X
------------------------

- At a minimum, Mac OS X 10.1 is required to run Tcl, but OS X 10.3 or higher is
recommended (certain [file] operations behave incorrectly on earlier releases).








|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
	http://groups.google.com/group/comp.lang.tcl/

- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on Mac OS X, see
	http://wiki.tcl.tk/_/ref?N=3753
	http://wiki.tcl.tk/_/ref?N=8361

- Please report bugs with Tcl on Mac OS X to the tracker:
	http://core.tcl.tk/tcl/reportlist

2. Using Tcl on Mac OS X
------------------------

- At a minimum, Mac OS X 10.1 is required to run Tcl, but OS X 10.3 or higher is
recommended (certain [file] operations behave incorrectly on earlier releases).

Changes to macosx/Tcl.xcode/project.pbxproj.

888
889
890
891
892
893
894

895
896
897
898
899
900
901
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };

		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };







>







888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
		F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,

				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;







>







1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,
				F96D449908F272BA004A47F5 /* tclWinThrd.h */,
				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;

Changes to macosx/Tcl.xcodeproj/project.pbxproj.

889
890
891
892
893
894
895

896
897
898
899
900
901
902
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };

		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };







>







889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
		F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
1819
1820
1821
1822
1823
1824
1825

1826
1827
1828
1829
1830
1831
1832
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,

				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;







>







1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,
				F96D449908F272BA004A47F5 /* tclWinThrd.h */,
				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;

Changes to macosx/configure.ac.

1
2
3
4
5
6
7
8
9
10
11
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

dnl	Ensure that the config (auto)headers support is used, then just
dnl	include the configure sources from ../unix:

m4_include(../unix/aclocal.m4)
m4_define(SC_USE_CONFIG_HEADERS)
m4_include(../unix/configure.in)





|





1
2
3
4
5
6
7
8
9
10
11
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

dnl	Ensure that the config (auto)headers support is used, then just 
dnl	include the configure sources from ../unix:

m4_include(../unix/aclocal.m4)
m4_define(SC_USE_CONFIG_HEADERS)
m4_include(../unix/configure.in)

Deleted tests-perf/clock.perf.tcl.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
#!/usr/bin/tclsh
# ------------------------------------------------------------------------
#
# test-performance.tcl --
#
#  This file provides common performance tests for comparison of tcl-speed
#  degradation by switching between branches.
#  (currently for clock ensemble only)
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#

array set in {-time 500}
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  array set in $argv
}

## common test performance framework:
if {![namespace exists ::tclTestPerf]} {
  source [file join [file dirname [info script]] test-performance.tcl]
}

namespace eval ::tclTestPerf-TclClock {

namespace path {::tclTestPerf}

## set testing defaults:
set ::env(TCL_TZ) :CET

# warm-up interpeter compiler env, clock platform-related features:

## warm-up test-related features (load clock.tcl, system zones, locales, etc.):
clock scan "" -gmt 1
clock scan ""
clock scan "" -timezone :CET
clock scan "" -format "" -locale en
clock scan "" -format "" -locale de

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

proc test-format {{reptime 1000}} {
  _test_run $reptime {
    # Format : short, week only (in gmt)
    {clock format 1482525936 -format "%u" -gmt 1}
    # Format : short, week only (system zone)
    {clock format 1482525936 -format "%u"}
    # Format : short, week only (CEST)
    {clock format 1482525936 -format "%u" -timezone :CET}
    # Format : date only (in gmt)
    {clock format 1482525936 -format "%Y-%m-%d" -gmt 1}
    # Format : date only (system zone)
    {clock format 1482525936 -format "%Y-%m-%d"}
    # Format : date only (CEST)
    {clock format 1482525936 -format "%Y-%m-%d" -timezone :CET}
    # Format : time only (in gmt)
    {clock format 1482525936 -format "%H:%M" -gmt 1}
    # Format : time only (system zone)
    {clock format 1482525936 -format "%H:%M"}
    # Format : time only (CEST)
    {clock format 1482525936 -format "%H:%M" -timezone :CET}
    # Format : time only (in gmt)
    {clock format 1482525936 -format "%H:%M:%S" -gmt 1}
    # Format : time only (system zone)
    {clock format 1482525936 -format "%H:%M:%S"}
    # Format : time only (CEST)
    {clock format 1482525936 -format "%H:%M:%S" -timezone :CET}
    # Format : default (in gmt)
    {clock format 1482525936 -gmt 1 -locale en}
    # Format : default (system zone)
    {clock format 1482525936 -locale en}
    # Format : default (CEST)
    {clock format 1482525936 -timezone :CET -locale en}
    # Format : ISO date-time (in gmt, numeric zone)
    {clock format 1246379400 -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1}
    # Format : ISO date-time (system zone, CEST, numeric zone)
    {clock format 1246379400 -format "%Y-%m-%dT%H:%M:%S %z"}
    # Format : ISO date-time (CEST, numeric zone)
    {clock format 1246379400 -format "%Y-%m-%dT%H:%M:%S %z" -timezone :CET}
    # Format : ISO date-time (system zone, CEST)
    {clock format 1246379400 -format "%Y-%m-%dT%H:%M:%S %Z"}
    # Format : julian day with time (in gmt):
    {clock format 1246379415 -format "%J %H:%M:%S" -gmt 1}
    # Format : julian day with time (system zone):
    {clock format 1246379415 -format "%J %H:%M:%S"}

    # Format : locale date-time (en):
    {clock format 1246379415 -format "%x %X" -locale en}
    # Format : locale date-time (de):
    {clock format 1246379415 -format "%x %X" -locale de}

    # Format : locale lookup table month:
    {clock format 1246379400 -format "%b" -locale en -gmt 1}
    # Format : locale lookup 2 tables - month and day:
    {clock format 1246379400 -format "%b %Od" -locale en -gmt 1}
    # Format : locale lookup 3 tables - week, month and day:
    {clock format 1246379400 -format "%a %b %Od" -locale en -gmt 1}
    # Format : locale lookup 4 tables - week, month, day and year:
    {clock format 1246379400 -format "%a %b %Od %Oy" -locale en -gmt 1}

    # Format : dynamic clock value (without converter caches):
    setup {set i 0}
    {clock format [incr i] -format "%Y-%m-%dT%H:%M:%S" -locale en -timezone :CET}
    cleanup {puts [clock format $i -format "%Y-%m-%dT%H:%M:%S" -locale en -timezone :CET]}
    # Format : dynamic clock value (without any converter caches, zone range overflow):
    setup {set i 0}
    {clock format [incr i 86400] -format "%Y-%m-%dT%H:%M:%S" -locale en -timezone :CET}
    cleanup {puts [clock format $i -format "%Y-%m-%dT%H:%M:%S" -locale en -timezone :CET]}

    # Format : dynamic format (cacheable)
    {clock format 1246379415 -format [string trim "%d.%m.%Y %H:%M:%S "] -gmt 1}

    # Format : all (in gmt, locale en)
    {clock format 1482525936 -format "%%a = %a | %%A = %A | %%b = %b | %%h = %h | %%B = %B | %%C = %C | %%d = %d | %%e = %e | %%g = %g | %%G = %G | %%H = %H | %%I = %I | %%j = %j | %%J = %J | %%k = %k | %%l = %l | %%m = %m | %%M = %M | %%N = %N | %%p = %p | %%P = %P | %%Q = %Q | %%s = %s | %%S = %S | %%t = %t | %%u = %u | %%U = %U | %%V = %V | %%w = %w | %%W = %W | %%y = %y | %%Y = %Y | %%z = %z | %%Z = %Z | %%n = %n | %%EE = %EE | %%EC = %EC | %%Ey = %Ey | %%n = %n | %%Od = %Od | %%Oe = %Oe | %%OH = %OH | %%Ok = %Ok | %%OI = %OI | %%Ol = %Ol | %%Om = %Om | %%OM = %OM | %%OS = %OS | %%Ou = %Ou | %%Ow = %Ow | %%Oy = %Oy" -gmt 1 -locale en}
    # Format : all (in CET, locale de)
    {clock format 1482525936 -format "%%a = %a | %%A = %A | %%b = %b | %%h = %h | %%B = %B | %%C = %C | %%d = %d | %%e = %e | %%g = %g | %%G = %G | %%H = %H | %%I = %I | %%j = %j | %%J = %J | %%k = %k | %%l = %l | %%m = %m | %%M = %M | %%N = %N | %%p = %p | %%P = %P | %%Q = %Q | %%s = %s | %%S = %S | %%t = %t | %%u = %u | %%U = %U | %%V = %V | %%w = %w | %%W = %W | %%y = %y | %%Y = %Y | %%z = %z | %%Z = %Z | %%n = %n | %%EE = %EE | %%EC = %EC | %%Ey = %Ey | %%n = %n | %%Od = %Od | %%Oe = %Oe | %%OH = %OH | %%Ok = %Ok | %%OI = %OI | %%Ol = %Ol | %%Om = %Om | %%OM = %OM | %%OS = %OS | %%Ou = %Ou | %%Ow = %Ow | %%Oy = %Oy" -timezone :CET -locale de}
  }
}

proc test-scan {{reptime 1000}} {
  _test_run -convert-result {clock format $_(r) -locale en} $reptime {
    # Scan : date (in gmt)
    {clock scan "25.11.2015" -format "%d.%m.%Y" -base 0 -gmt 1}
    # Scan : date (system time zone, with base)
    {clock scan "25.11.2015" -format "%d.%m.%Y" -base 0}
    # Scan : date (system time zone, without base)
    {clock scan "25.11.2015" -format "%d.%m.%Y"}
    # Scan : greedy match
    {clock scan "111" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "1111" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "11111" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "111111" -format "%d%m%y" -base 0 -gmt 1}
    # Scan : greedy match (space separated)
    {clock scan "1 1 1" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "111 1" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "1 111" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "1 11 1" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "1 11 11" -format "%d%m%y" -base 0 -gmt 1}
    {clock scan "11 11 11" -format "%d%m%y" -base 0 -gmt 1}

    # Scan : time (in gmt)
    {clock scan "10:35:55" -format "%H:%M:%S" -base 1000000000 -gmt 1}
    # Scan : time (system time zone, with base)
    {clock scan "10:35:55" -format "%H:%M:%S" -base 1000000000}
    # Scan : time (gmt, without base)
    {clock scan "10:35:55" -format "%H:%M:%S" -gmt 1}
    # Scan : time (system time zone, without base)
    {clock scan "10:35:55" -format "%H:%M:%S"}

    # Scan : date-time (in gmt)
    {clock scan "25.11.2015 10:35:55" -format "%d.%m.%Y %H:%M:%S" -base 0 -gmt 1}
    # Scan : date-time (system time zone with base)
    {clock scan "25.11.2015 10:35:55" -format "%d.%m.%Y %H:%M:%S" -base 0}
    # Scan : date-time (system time zone without base)
    {clock scan "25.11.2015 10:35:55" -format "%d.%m.%Y %H:%M:%S"}

    # Scan : julian day in gmt
    {clock scan 2451545 -format %J -gmt 1}
    # Scan : julian day in system TZ
    {clock scan 2451545 -format %J}
    # Scan : julian day in other TZ
    {clock scan 2451545 -format %J -timezone +0200}
    # Scan : julian day with time:
    {clock scan "2451545 10:20:30" -format "%J %H:%M:%S"}
    # Scan : julian day with time (greedy match):
    {clock scan "2451545 102030" -format "%J%H%M%S"}

    # Scan : century, lookup table month
    {clock scan {1970 Jan 2} -format {%C%y %b %d} -locale en -gmt 1}
    # Scan : century, lookup table month and day (both entries are first)
    {clock scan {1970 Jan 01} -format {%C%y %b %Od} -locale en -gmt 1}
    # Scan : century, lookup table month and day (list scan: entries with position 12 / 31)
    {clock scan {2016 Dec 31} -format {%C%y %b %Od} -locale en -gmt 1}

    # Scan : ISO date-time (CEST)
    {clock scan "2009-06-30T18:30:00+02:00" -format "%Y-%m-%dT%H:%M:%S%z"}
    {clock scan "2009-06-30T18:30:00 CEST" -format "%Y-%m-%dT%H:%M:%S %z"}
    # Scan : ISO date-time (UTC)
    {clock scan "2009-06-30T18:30:00Z" -format "%Y-%m-%dT%H:%M:%S%z"}
    {clock scan "2009-06-30T18:30:00 UTC" -format "%Y-%m-%dT%H:%M:%S %z"}

    # Scan : locale date-time (en):
    {clock scan "06/30/2009 18:30:15" -format "%x %X" -gmt 1 -locale en}
    # Scan : locale date-time (de):
    {clock scan "30.06.2009 18:30:15" -format "%x %X" -gmt 1 -locale de}

    # Scan : dynamic format (cacheable)
    {clock scan "25.11.2015 10:35:55" -format [string trim "%d.%m.%Y %H:%M:%S "] -base 0 -gmt 1}

    break
    # # Scan : long format test (allock chain)
    # {clock scan "25.11.2015" -format "%d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y" -base 0 -gmt 1}
    # # Scan : dynamic, very long format test (create obj representation, allock chain, GC, etc):
    # {clock scan "25.11.2015" -format [string repeat "[incr i] %d.%m.%Y %d.%m.%Y" 10] -base 0 -gmt 1}
    # # Scan : again:
    # {clock scan "25.11.2015" -format [string repeat "[incr i -1] %d.%m.%Y %d.%m.%Y" 10] -base 0 -gmt 1}
  }
}

proc test-freescan {{reptime 1000}} {
  _test_run -convert-result {clock format $_(r) -locale en}  $reptime {
    # FreeScan : relative date
    {clock scan "5 years 18 months 385 days" -base 0 -gmt 1}
    # FreeScan : relative date with relative weekday
    {clock scan "5 years 18 months 385 days Fri" -base 0 -gmt 1}
    # FreeScan : relative date with ordinal month
    {clock scan "5 years 18 months 385 days next 1 January" -base 0 -gmt 1}
    # FreeScan : relative date with ordinal month and relative weekday
    {clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1}
    # FreeScan : ordinal month
    {clock scan "next January" -base 0 -gmt 1}
    # FreeScan : relative week
    {clock scan "next Fri" -base 0 -gmt 1}
    # FreeScan : relative weekday and week offset
    {clock scan "next January + 2 week" -base 0 -gmt 1}
    # FreeScan : time only with base
    {clock scan "19:18:30" -base 148863600 -gmt 1}
    # FreeScan : time only without base, gmt
    {clock scan "19:18:30" -gmt 1}
    # FreeScan : time only without base, system
    {clock scan "19:18:30"}
    # FreeScan : date, system time zone
    {clock scan "05/08/2016 20:18:30"}
    # FreeScan : date, supplied time zone
    {clock scan "05/08/2016 20:18:30" -timezone :CET}
    # FreeScan : date, supplied gmt (equivalent -timezone :GMT)
    {clock scan "05/08/2016 20:18:30" -gmt 1}
    # FreeScan : date, supplied time zone gmt
    {clock scan "05/08/2016 20:18:30" -timezone :GMT}
    # FreeScan : time only, numeric zone in string, base time gmt (exchange zones between gmt / -0500)
    {clock scan "20:18:30 -0500" -base 148863600 -gmt 1}
    # FreeScan : time only, zone in string (exchange zones between system / gmt)
    {clock scan "19:18:30 GMT" -base 148863600}
    # FreeScan : fast switch of zones in cycle - GMT, MST, CET (system) and EST
    {clock scan "19:18:30 MST" -base 148863600 -gmt 1
     clock scan "19:18:30 EST" -base 148863600
    }
  }
}

proc test-add {{reptime 1000}} {
  set tests {
    # Add : years
    {clock add 1246379415 5 years -gmt 1}
    # Add : months
    {clock add 1246379415 18 months -gmt 1}
    # Add : weeks
    {clock add 1246379415 20 weeks -gmt 1}
    # Add : days
    {clock add 1246379415 385 days -gmt 1}
    # Add : weekdays
    {clock add 1246379415 3 weekdays -gmt 1}

    # Add : hours
    {clock add 1246379415 5 hours -gmt 1}
    # Add : minutes
    {clock add 1246379415 55 minutes -gmt 1}
    # Add : seconds
    {clock add 1246379415 100 seconds -gmt 1}

    # Add : +/- in gmt
    {clock add 1246379415 -5 years +21 months -20 weeks +386 days -19 hours +30 minutes -10 seconds -gmt 1}
    # Add : +/- in system timezone
    {clock add 1246379415 -5 years +21 months -20 weeks +386 days -19 hours +30 minutes -10 seconds -timezone :CET}

    # Add : gmt
    {clock add 1246379415 -5 years 18 months 366 days 5 hours 30 minutes 10 seconds -gmt 1}
    # Add : system timezone
    {clock add 1246379415 -5 years 18 months 366 days 5 hours 30 minutes 10 seconds -timezone :CET}

    # Add : all in gmt
    {clock add 1246379415 4 years 18 months 50 weeks 378 days 3 weekdays 5 hours 30 minutes 10 seconds -gmt 1}
    # Add : all in system timezone
    {clock add 1246379415 4 years 18 months 50 weeks 378 days 3 weekdays 5 hours 30 minutes 10 seconds -timezone :CET}

  }
  # if does not support add of weekdays:
  if {[catch {clock add 0 3 weekdays -gmt 1}]} {
    regsub -all {\mweekdays\M} $tests "days" tests
  }
  _test_run -convert-result {clock format $_(r) -locale en} $reptime $tests
}

proc test-convert {{reptime 1000}} {
  _test_run $reptime {
    # Convert locale (en -> de):
    {clock format [clock scan "Tue May 30 2017" -format "%a %b %d %Y" -gmt 1 -locale en] -format "%a %b %d %Y" -gmt 1 -locale de}
    # Convert locale (de -> en):
    {clock format [clock scan "Di Mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale de] -format "%a %b %d %Y" -gmt 1 -locale en}

    # Convert TZ: direct
    {clock format [clock scan "19:18:30" -base 148863600 -timezone EST] -timezone MST}
    {clock format [clock scan "19:18:30" -base 148863600 -timezone MST] -timezone EST}
    # Convert TZ: included in scan string & format
    {clock format [clock scan "19:18:30 EST" -base 148863600] -format "%H:%M:%S %z" -timezone MST}
    {clock format [clock scan "19:18:30 EST" -base 148863600] -format "%H:%M:%S %z" -timezone EST}

    # Format locale 1x: comparison values
    {clock format 0 -gmt 1 -locale en}
    {clock format 0 -gmt 1 -locale de}
    {clock format 0 -gmt 1 -locale fr}
    # Format locale 2x: without switching locale (en, en)
    {clock format 0 -gmt 1 -locale en; clock format 0 -gmt 1 -locale en}
    # Format locale 2x: with switching locale (en, de)
    {clock format 0 -gmt 1 -locale en; clock format 0 -gmt 1 -locale de}
    # Format locale 3x: without switching locale (en, en, en)
    {clock format 0 -gmt 1 -locale en; clock format 0 -gmt 1 -locale en; clock format 0 -gmt 1 -locale en}
    # Format locale 3x: with switching locale (en, de, fr)
    {clock format 0 -gmt 1 -locale en; clock format 0 -gmt 1 -locale de; clock format 0 -gmt 1 -locale fr}

    # Scan locale 2x: without switching locale (en, en) + (de, de)
    {clock scan "Tue May 30 2017" -format "%a %b %d %Y" -gmt 1 -locale en; clock scan "Tue May 30 2017" -format "%a %b %d %Y" -gmt 1 -locale en}
    {clock scan "Di Mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale de; clock scan "Di Mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale de}
    # Scan locale 2x: with switching locale (en, de)
    {clock scan "Tue May 30 2017" -format "%a %b %d %Y" -gmt 1 -locale en; clock scan "Di Mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale de}
    # Scan locale 3x: with switching locale (en, de, fr)
    {clock scan "Tue May 30 2017" -format "%a %b %d %Y" -gmt 1 -locale en; clock scan "Di Mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale de; clock scan "mar. mai 30 2017" -format "%a %b %d %Y" -gmt 1 -locale fr}

    # Format TZ 2x: comparison values
    {clock format 0 -timezone CET -format "%Y-%m-%d %H:%M:%S %z"}
    {clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"}
    # Format TZ 2x: without switching
    {clock format 0 -timezone CET -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone CET -format "%Y-%m-%d %H:%M:%S %z"}
    {clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"}
    # Format TZ 2x: with switching
    {clock format 0 -timezone CET -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"}
    # Format TZ 3x: with switching (CET, EST, MST)
    {clock format 0 -timezone CET -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone MST -format "%Y-%m-%d %H:%M:%S %z"}
    # Format TZ 3x: with switching (GMT, EST, MST)
    {clock format 0 -gmt 1 -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone EST -format "%Y-%m-%d %H:%M:%S %z"; clock format 0 -timezone MST -format "%Y-%m-%d %H:%M:%S %z"}

    # FreeScan TZ 2x (+1 system-default): without switching TZ
    {clock scan "19:18:30 MST" -base 148863600; clock scan "19:18:30 MST" -base 148863600}
    {clock scan "19:18:30 EST" -base 148863600; clock scan "19:18:30 EST" -base 148863600}
    # FreeScan TZ 2x (+1 system-default): with switching TZ
    {clock scan "19:18:30 MST" -base 148863600; clock scan "19:18:30 EST" -base 148863600}
    # FreeScan TZ 2x (+1 gmt, +1 system-default)
    {clock scan "19:18:30 MST" -base 148863600 -gmt 1; clock scan "19:18:30 EST" -base 148863600}

    # Scan TZ: comparison included in scan string vs. given
    {clock scan "2009-06-30T18:30:00 CEST" -format "%Y-%m-%dT%H:%M:%S %z"}
    {clock scan "2009-06-30T18:30:00 CET" -format "%Y-%m-%dT%H:%M:%S %z"}
    {clock scan "2009-06-30T18:30:00" -timezone CET -format "%Y-%m-%dT%H:%M:%S"}
  }
}

proc test-other {{reptime 1000}} {
  _test_run $reptime {
    # Bad zone
    {catch {clock scan "1 day" -timezone BAD_ZONE -locale en}}

    # Scan : julian day (overflow)
    {catch {clock scan 5373485 -format %J}}

    # Scan : test rotate of GC objects (format is dynamic, so tcl-obj removed with last reference)
    {set i 0; time { clock scan "[incr i] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}
    # Scan : test reusability of GC objects (format is dynamic, so tcl-obj removed with last reference)
    {set i 50; time { clock scan "[incr i -1] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}
  }
}

proc test-ensemble-perf {{reptime 1000}} {
  _test_run $reptime {
    # Clock clicks (ensemble)
    {clock clicks}
    # Clock clicks (direct)
    {::tcl::clock::clicks}
    # Clock seconds (ensemble)
    {clock seconds}
    # Clock seconds (direct)
    {::tcl::clock::seconds}
    # Clock microseconds (ensemble)
    {clock microseconds}
    # Clock microseconds (direct)
    {::tcl::clock::microseconds}
    # Clock scan (ensemble)
    {clock scan ""}
    # Clock scan (direct)
    {::tcl::clock::scan ""}
    # Clock format (ensemble)
    {clock format 0 -f %s}
    # Clock format (direct)
    {::tcl::clock::format 0 -f %s}
  }
}

proc test {{reptime 1000}} {
  puts ""
  test-ensemble-perf [expr {$reptime / 2}]; #fast enough
  test-format $reptime
  test-scan $reptime
  test-freescan $reptime
  test-add $reptime
  test-convert [expr {$reptime / 2}]; #fast enough
  test-other $reptime

  puts \n**OK**
}

}; # end of ::tclTestPerf-TclClock

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

# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  ::tclTestPerf-TclClock::test $in(-time)
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































































































































































































































































































































































































































































Deleted tests-perf/test-performance.tcl.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# ------------------------------------------------------------------------
#
# test-performance.tcl --
#
#  This file provides common performance tests for comparison of tcl-speed
#  degradation or regression by switching between branches.
#
#  To execute test case evaluate direct corresponding file "tests-perf\*.perf.tcl".
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#

namespace eval ::tclTestPerf {
# warm-up interpeter compiler env, calibrate timerate measurement functionality:

# if no timerate here - import from unsupported:
if {[namespace which -command timerate] eq {}} {
  namespace inscope ::tcl::unsupported {namespace export timerate}
  namespace import ::tcl::unsupported::timerate
}

# if not yet calibrated:
if {[lindex [timerate {} 10] 6] >= (10-1)} {
  puts -nonewline "Calibration ... "; flush stdout
  puts "done: [lrange \
    [timerate -calibrate {}] \
  0 1]"
}

proc {**STOP**} {args} {
  return -code error -level 4 "**STOP** in [info level [expr {[info level]-2}]] [join $args { }]"
}

proc _test_get_commands {lst} {
  regsub -all {(?:^|\n)[ \t]*(\#[^\n]*|\msetup\M[^\n]*|\mcleanup\M[^\n]*)(?=\n\s*(?:[\{\#]|setup|cleanup|$))} $lst "\n{\\1}"
}

proc _test_out_total {} {
  upvar _ _

  set tcnt [llength $_(itm)]
  if {!$tcnt} {
    puts ""
    return
  }

  set mintm 0x7fffffff
  set maxtm 0
  set nettm 0
  set wtm 0
  set wcnt 0
  set i 0
  foreach tm $_(itm) {
    if {[llength $tm] > 6} {
      set nettm [expr {$nettm + [lindex $tm 6]}]
    }
    set wtm [expr {$wtm + [lindex $tm 0]}]
    set wcnt [expr {$wcnt + [lindex $tm 2]}]
    set tm [lindex $tm 0]
    if {$tm > $maxtm} {set maxtm $tm; set maxi $i}
    if {$tm < $mintm} {set mintm $tm; set mini $i}
    incr i
  }

  puts [string repeat ** 40]
  set s [format "%d cases in %.2f sec." $tcnt [expr {([clock milliseconds] - $_(starttime)) / 1000.0}]]
  if {$nettm > 0} {
    append s [format " (%.2f net-sec.)" [expr {$nettm / 1000.0}]]
  }
  puts "Total $s:"
  lset _(m) 0 [format %.6f $wtm]
  lset _(m) 2 $wcnt
  lset _(m) 4 [format %.3f [expr {$wcnt / (($nettm ? $nettm : ($tcnt * [lindex $_(reptime) 0])) / 1000.0)}]]
  if {[llength $_(m)] > 6} {
    lset _(m) 6 [format %.3f $nettm]
  }
  puts $_(m)
  puts "Average:"
  lset _(m) 0 [format %.6f [expr {[lindex $_(m) 0] / $tcnt}]]
  lset _(m) 2 [expr {[lindex $_(m) 2] / $tcnt}]
  if {[llength $_(m)] > 6} {
    lset _(m) 6 [format %.3f [expr {[lindex $_(m) 6] / $tcnt}]]
    lset _(m) 4 [format %.0f [expr {[lindex $_(m) 2] / [lindex $_(m) 6] * 1000}]]
  }
  puts $_(m)
  puts "Min:"
  puts [lindex $_(itm) $mini]
  puts "Max:"
  puts [lindex $_(itm) $maxi]
  puts [string repeat ** 40]
  puts ""
  unset -nocomplain _(itm) _(starttime)
}

proc _test_start {reptime} {
  upvar _ _
  array set _ [list itm {} reptime $reptime starttime [clock milliseconds] -from-run 0]
}

proc _test_iter {args} {
  if {[llength $args] > 2} {
    return -code error "wrong # args: should be \"[lindex [info level [info level]] 0] ?level? measure-result\""
  }
  set lvl 1
  if {[llength $args] > 1} {
    set args [lassign $args lvl]
  }
  upvar $lvl _ _
  puts [set _(m) {*}$args]
  lappend _(itm) $_(m)
  puts ""
}

proc _adjust_maxcount {reptime maxcount} {
  if {[llength $reptime] > 1} {
    lreplace $reptime 1 1 [expr {min($maxcount,[lindex $reptime 1])}]
  } else {
    lappend reptime $maxcount
  }
}

proc _test_run {args} {
  upvar _ _
  # parse args:
  array set _ {-no-result 0 -uplevel 0 -convert-result {}}
  while {[llength $args] > 2} {
    if {![info exists _([set o [lindex $args 0]])]} {
      break
    }
    if {[string is boolean -strict $_($o)]} {
      set _($o) [expr {! $_($o)}]
      set args [lrange $args 1 end]
    } else {
      if {[llength $args] <= 2} {
        return -code error "value expected for option $o"
      }
      set _($o) [lindex $args 1]
      set args [lrange $args 2 end]
    }
  }
  unset -nocomplain o
  if {[llength $args] < 2 || [llength $args] > 3} {
    return -code error "wrong # args: should be \"[lindex [info level [info level]] 0] ?-no-result? reptime lst ?outcmd?\""
  }
  set _(outcmd) {puts}
  set args [lassign $args reptime lst]
  if {[llength $args]} {
    set _(outcmd) [lindex $args 0]
  }
  # avoid output if only once:
  if {[lindex $reptime 0] <= 1 || ([llength $reptime] > 1 && [lindex $reptime 1] == 1)} {
    set _(-no-result) 1
  }
  if {![info exists _(itm)]} {
    array set _ [list itm {} reptime $reptime starttime [clock milliseconds] -from-run 1]
  } else {
    array set _ [list reptime $reptime]
  }

  # process measurement:
  foreach _(c) [_test_get_commands $lst] {
    {*}$_(outcmd) "% [regsub -all {\n[ \t]*} $_(c) {; }]"
    if {[regexp {^\s*\#} $_(c)]} continue
    if {[regexp {^\s*(?:setup|cleanup)\s+} $_(c)]} {
      set _(c) [lindex $_(c) 1]
      if {$_(-uplevel)} {
        set _(c) [list uplevel 1 $_(c)]
      }
      {*}$_(outcmd) [if 1 $_(c)]
      continue
    }
    if {$_(-uplevel)} {
      set _(c) [list uplevel 1 $_(c)]
    }
    set _(ittime) $_(reptime)
    # if output result (and not once):
    if {!$_(-no-result)} {
      set _(r) [if 1 $_(c)]
      if {$_(-convert-result) ne ""} { set _(r) [if 1 $_(-convert-result)] }
      {*}$_(outcmd) $_(r)
      if {[llength $_(ittime)] > 1} { # decrement max-count
        lset _(ittime) 1 [expr {[lindex $_(ittime) 1] - 1}]
      }
    }
    {*}$_(outcmd) [set _(m) [timerate $_(c) {*}$_(ittime)]]
    lappend _(itm) $_(m)
    {*}$_(outcmd) ""
  }
  if {$_(-from-run)} {
    _test_out_total
  }
}

}; # end of namespace ::tclTestPerf
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































































































































































































































































































Deleted tests-perf/timer-event.perf.tcl.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#!/usr/bin/tclsh

# ------------------------------------------------------------------------
#
# timer-event.perf.tcl --
#
#  This file provides performance tests for comparison of tcl-speed
#  of timer events (event-driven tcl-handling).
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {
  source [file join [file dirname [info script]] test-performance.tcl]
}


namespace eval ::tclTestPerf-Timer-Event {

namespace path {::tclTestPerf}

proc test-queue {{reptime {1000 10000}}} {

  set howmuch [lindex $reptime 1]

  # because of extremely short measurement times by tests below, wait a little bit (warming-up),
  # to minimize influence of the time-gradation (just for better dispersion resp. result-comparison)
  timerate {after 0} 156

  puts "*** up to $howmuch events ***"
  # single iteration by update, so using -no-result (measure only):
  _test_run -no-result $reptime [string map [list \{*\}\$reptime $reptime \$howmuch $howmuch \\# \#] {
    # generate up to $howmuch idle-events:
    {after idle {set foo bar}}
    # update / after idle:
    {update; if {![llength [after info]]} break}

    # generate up to $howmuch idle-events:
    {after idle {set foo bar}}
    # update idletasks / after idle:
    {update idletasks; if {![llength [after info]]} break}

    # generate up to $howmuch immediate events:
    {after 0 {set foo bar}}
    # update / after 0:
    {update; if {![llength [after info]]} break}

    # generate up to $howmuch 1-ms events:
    {after 1 {set foo bar}}
    setup {after 1}
    # update / after 1:
    {update; if {![llength [after info]]} break}

    # generate up to $howmuch immediate events (+ 1 event of the second generation):
    {after 0 {after 0 {}}}
    # update / after 0 (double generation):
    {update; if {![llength [after info]]} break}

    # cancel forwards "after idle" / $howmuch idle-events in queue:
    setup {set i 0; timerate {set ev([incr i]) [after idle {set foo bar}]} {*}$reptime}
    setup {set le $i; set i 0; list 1 .. $le; # cancel up to $howmuch events}
    {after cancel $ev([incr i]); if {$i >= $le} break}
    cleanup {update; unset -nocomplain ev}
    # cancel backwards "after idle" / $howmuch idle-events in queue:
    setup {set i 0; timerate {set ev([incr i]) [after idle {set foo bar}]} {*}$reptime}
    setup {set le $i; incr i; list $le .. 1; # cancel up to $howmuch events}
    {after cancel $ev([incr i -1]); if {$i <= 1} break}
    cleanup {update; unset -nocomplain ev}

    # cancel forwards "after 0" / $howmuch timer-events in queue:
    setup {set i 0; timerate {set ev([incr i]) [after 0 {set foo bar}]} {*}$reptime}
    setup {set le $i; set i 0; list 1 .. $le; # cancel up to $howmuch events}
    {after cancel $ev([incr i]); if {$i >= $le} break}
    cleanup {update; unset -nocomplain ev}
    # cancel backwards "after 0" / $howmuch timer-events in queue:
    setup {set i 0; timerate {set ev([incr i]) [after 0 {set foo bar}]} {*}$reptime}
    setup {set le $i; incr i; list $le .. 1; # cancel up to $howmuch events}
    {after cancel $ev([incr i -1]); if {$i <= 1} break}
    cleanup {update; unset -nocomplain ev}

    # end $howmuch events.
    cleanup {if [llength [after info]] {error "unexpected: [llength [after info]] events are still there."}}
  }]
}

proc test-access {{reptime {1000 5000}}} {
  set howmuch [lindex $reptime 1]

  _test_run $reptime [string map [list \{*\}\$reptime $reptime \$howmuch $howmuch] {
    # event random access: after idle + after info (by $howmuch events)
    setup {set i -1; timerate {set ev([incr i]) [after idle {}]} {*}$reptime}
    {after info $ev([expr {int(rand()*$i)}])}
    cleanup {update; unset -nocomplain ev}
    # event random access: after 0 + after info (by $howmuch events)
    setup {set i -1; timerate {set ev([incr i]) [after 0 {}]} {*}$reptime}
    {after info $ev([expr {int(rand()*$i)}])}
    cleanup {update; unset -nocomplain ev}

    # end $howmuch events.
    cleanup {if [llength [after info]] {error "unexpected: [llength [after info]] events are still there."}}
  }]
}

proc test-exec {{reptime 1000}} {
  _test_run $reptime {
    # after idle + after cancel
    {after cancel [after idle {set foo bar}]}
    # after 0 + after cancel
    {after cancel [after 0 {set foo bar}]}
    # after idle + update idletasks
    {after idle {set foo bar}; update idletasks}
    # after idle + update
    {after idle {set foo bar}; update}
    # immediate: after 0 + update
    {after 0 {set foo bar}; update}
    # delayed: after 1 + update
    {after 1 {set foo bar}; update}
    # empty update:
    {update}
    # empty update idle tasks:
    {update idletasks}

    # simple shortest sleep:
    {after 0}
  }
}

proc test-nrt-capability {{reptime 1000}} {
  _test_run $reptime {
    # comparison values:
    {after 0 {set a 5}; update}
    {after 0 {set a 5}; vwait a}

    # conditional vwait with very brief wait-time:
    {after 1 {set a timeout}; vwait a; expr {$::a ne "timeout" ? 1 : "0[unset ::a]"}}
    {after 0 {set a timeout}; vwait a; expr {$::a ne "timeout" ? 1 : "0[unset ::a]"}}
  }
}

proc test-long {{reptime 1000}} {
  _test_run $reptime {
    # in-between important event by amount of idle events:
    {time {after idle {after 30}} 10; after 1 {set important 1}; vwait important;}
    cleanup {foreach i [after info] {after cancel $i}}
    # in-between important event (of new generation) by amount of idle events:
    {time {after idle {after 30}} 10; after 1 {after 0 {set important 1}}; vwait important;}
    cleanup {foreach i [after info] {after cancel $i}}
  }
}

proc test {{reptime 1000}} {
  test-exec $reptime
  foreach howmuch {5000 50000} {
    test-access [list $reptime $howmuch]
  }
  test-nrt-capability $reptime
  test-long $reptime

  puts ""
  foreach howmuch { 10000 20000 40000 60000 } {
    test-queue [list $reptime $howmuch]
  }

  puts \n**OK**
}

}; # end of ::tclTestPerf-Timer-Event

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

# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  array set in {-time 500}
  array set in $argv
  ::tclTestPerf-Timer-Event::test $in(-time)
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































































































































































































Changes to tests/all.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# all.tcl --
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all.test" when running tcltest
# in this directory.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.5
package require tcltest 2.5
namespace import tcltest::*
configure {*}$argv -testdir [file dir [info script]]
set ErrorOnFailures [info exists env(ERROR_ON_FAILURES)]
unset -nocomplain env(ERROR_ON_FAILURES)
if {[runAllTests] && $ErrorOnFailures} {exit 1}













|


<
<
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


17
# all.tcl --
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all.test" when running tcltest
# in this directory.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.5
package require tcltest 2.2
namespace import tcltest::*
configure {*}$argv -testdir [file dir [info script]]


runAllTests

Changes to tests/async.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    namespace import -force ::tcltest::*
}

testConstraint testasync [llength [info commands testasync]]
testConstraint threaded [expr {
    [info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)
}]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

proc async1 {result code} {
    global aresult acode
    set aresult $result
    set acode $code
    return "new result"
}







<







16
17
18
19
20
21
22

23
24
25
26
27
28
29
    namespace import -force ::tcltest::*
}

testConstraint testasync [llength [info commands testasync]]
testConstraint threaded [expr {
    [info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)
}]


proc async1 {result code} {
    global aresult acode
    set aresult $result
    set acode $code
    return "new result"
}
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    set hm [testasync create async3]
} -body {
    hang1 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}
test async-4.2 {async interrupting straight bytecode sequence} -constraints {
    testasync threaded knownMsvcBug
} -setup {
    set hm [testasync create async3]
} -body {
    hang2 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}
test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
    testasync threaded knownMsvcBug
} -setup {
    set hm [testasync create async3]
} -body {
    hang3 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}







|








|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
    set hm [testasync create async3]
} -body {
    hang1 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}
test async-4.2 {async interrupting straight bytecode sequence} -constraints {
    testasync threaded
} -setup {
    set hm [testasync create async3]
} -body {
    hang2 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}
test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
    testasync threaded
} -setup {
    set hm [testasync create async3]
} -body {
    hang3 $hm
} -result {test pattern} -cleanup {
    testasync delete $hm
}

Changes to tests/chanio.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- tcl -*-
# Functionality covered: operation of all IO commands, and all procedures
# defined in generic/tclIO.c.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[catch {package require tcltest 2}]} {
    chan puts stderr "Skipping tests in [info script].  tcltest 2 required."
    return
}
namespace eval ::tcl::test::io {
    namespace import ::tcltest::*




|
|
|





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- tcl -*-
# Functionality covered: operation of all IO commands, and all procedures
# defined in generic/tclIO.c.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[catch {package require tcltest 2}]} {
    chan puts stderr "Skipping tests in [info script].  tcltest 2 required."
    return
}
namespace eval ::tcl::test::io {
    namespace import ::tcltest::*
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    testConstraint openpipe         1
    testConstraint fileevent        [llength [info commands fileevent]]
    testConstraint fcopy            [llength [info commands fcopy]]
    testConstraint testfevent       [llength [info commands testfevent]]
    testConstraint testchannelevent [llength [info commands testchannelevent]]
    testConstraint testmainthread   [llength [info commands testmainthread]]
    testConstraint testthread       [llength [info commands testthread]]
    testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

    # You need a *very* special environment to do some tests.  In particular,
    # many file systems do not support large-files...
    testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

    # some tests can only be run is umask is 2 if "umask" cannot be run, the
    # tests will be skipped.
    set umaskValue 0
    testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]

    testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]

    # set up a long data file for some of the following tests








<

|
|


|
|







34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
    testConstraint openpipe         1
    testConstraint fileevent        [llength [info commands fileevent]]
    testConstraint fcopy            [llength [info commands fcopy]]
    testConstraint testfevent       [llength [info commands testfevent]]
    testConstraint testchannelevent [llength [info commands testchannelevent]]
    testConstraint testmainthread   [llength [info commands testmainthread]]
    testConstraint testthread       [llength [info commands testthread]]


    # You need a *very* special environment to do some tests.  In
    # particular, many file systems do not support large-files...
    testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

    # some tests can only be run is umask is 2
    # if "umask" cannot be run, the tests will be skipped.
    set umaskValue 0
    testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]

    testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]

    # set up a long data file for some of the following tests

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
	set f [open $file]
	chan configure $f -translation binary
	set a [chan read $f]
	chan close $f
	return $a
    }

    # Wrapper round butt-ugly pipe syntax
    proc openpipe {{mode r+} args} {
	open "|[list [interpreter] {*}$args]" $mode
    }

test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
    # no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
    set f [open $path(test1) w]
    chan configure $f -encoding binary







<
<
<
<
<







87
88
89
90
91
92
93





94
95
96
97
98
99
100
	set f [open $file]
	chan configure $f -translation binary
	set a [chan read $f]
	chan close $f
	return $a
    }






test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
    # no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
    set f [open $path(test1) w]
    chan configure $f -encoding binary
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
140
141
142

143

144

145
146
147
148
149

150

151

152

153
154
155
156
157

158


159
160
161
162
163

164


165
166
167
168
169


170
171
172
173

174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231
232

233
234
235
236
237
238

239
240
241

242
243
244
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
    chan close $f
    contents $path(test1)
} "a\x93\xe1\x00"
set path(test2) [makeFile {} test2]
test chan-io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug applied to
    # tcl will cause tcl, more specifically WriteChars, to go into an infinite

    # loop.
    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp
    chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
    chan close           $f
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"

test chan-io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends escape bytes, check

    # for the case where the escape bytes overflow the current IO buffer. The
    # bytes should be moved into a new buffer.

    set data "1234567890 [format %c 12399]"

    set sizes [list]

    # With default buffer size
    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size equal to the length of the data, the escape bytes would

    # go into the next buffer.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 16
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that is large enough to hold 1 byte of escaped data,

    # but not all 3. This should not write the escape bytes to the first

    # buffer and then again to the second buffer.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 17
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that can hold 2 out of 3 bytes of escaped data.


    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 18
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that can hold all the data and escape bytes.


    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 19
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]


} {19 19 19 19 19}

test chan-io-2.1 {WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    chan configure $f  -encoding binary -buffersize 16 -translation crlf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-2.2 {WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffersize 16 -translation crlf
    chan puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-2.3 {WriteBytes: flush on line} -body {
    # Tcl "line" buffering has weird behavior: if current buffer contains a
    # \n, entire buffer gets flushed.  Logical behavior would be to flush only
    # up to the \n.

    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    contents $path(test1)
} -cleanup {
    chan close $f

} -result "\r\n12"
test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     chan configure $f -encoding binary -buffering line -translation lf \
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffersize 16 -translation crlf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffersize 16 -translation crlf
    chan puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} -body {
    # Tcl "line" buffering has weird behavior: if current buffer contains a
    # \n, entire buffer gets flushed.  Logical behavior would be to flush only
    # up to the \n.

    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    contents $path(test1)
} -cleanup {
    chan close $f

} -result "\r\n12"
test chan-io-3.4 {WriteChars: loop over stage buffer} {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 16
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.5 {WriteChars: saved != 0} {
    # Bytes produced by UtfToExternal from end of last channel buffer had to
    # be moved to beginning of next channel buffer to preserve requested
    # buffersize.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
    # One incomplete UTF-8 character at end of staging buffer. Backup in src
    # to the beginning of that UTF-8 character and try again.
    #
    # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
    # (first two bytes of \uff21 in UTF-8). Given those two bytes try
    # translating them again, find that no bytes are read produced, and break
    # to outer loop where those two bytes will have the remaining 4 bytes (the
    # last byte of \uff21 plus the all of \uff22) appended.

    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis -buffersize 16
    chan puts -nonewline $f "12345678901234\uff21\uff22"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
    # When translating UTF-8 to external, the produced bytes went past end of
    # the channel buffer. This is done on purpose - we then truncate the bytes
    # at the end of the partial character to preserve the requested blocksize
    # on flush. The truncated bytes are moved to the beginning of the next
    # channel buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation lf \
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-4.1 {TranslateOutputEOL: lf} {
    # search for \n

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation lf
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\n" "abcde\n"]
test chan-io-4.2 {TranslateOutputEOL: cr} {
    # search for \n, replace with \r

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation cr
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\r" "abcde\r"]
test chan-io-4.3 {TranslateOutputEOL: crlf} {
    # simple case: search for \n, replace with \r

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation crlf
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\r\n" "abcde\r\n"]
test chan-io-4.4 {TranslateOutputEOL: crlf} {
    # Keep storing more bytes in output buffer until output buffer is full. We
    # have 13 bytes initially that would turn into 18 bytes. Fill dest buffer
    # while (dstEnd < dstMax).

    set f [open $path(test1) w]
    chan configure $f -translation crlf -buffersize 16
    chan puts -nonewline $f "1234567\n\n\n\n\nA"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "1234567\r\n\r\n\r\n\r\n\r" "1234567\r\n\r\n\r\n\r\n\r\nA"]
test chan-io-4.5 {TranslateOutputEOL: crlf} {
    # Check for overflow of the destination buffer

    set f [open $path(test1) w]
    chan configure $f -translation crlf -buffersize 12
    chan puts -nonewline $f "12345678901\n456789012345678901234"
    chan close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test chan-io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    chan configure $f
    chan puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test chan-io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]







|
|
>
|
|
|
|
|


>

|
>
|
|
>

>

>






>
|
>

>





>
|
>
|
>
|
>





>
|
>
>





>
|
>
>





>
>




>









>







|
|
|
|
>



|
<

>
|












>









>







|
|
|
|
>



|
<

>
|


>

|






|
|
|
>

|






|
|


|

|
|
>








|
|
|
|
|
>

|

















>









>









>








|
|
|
>









>









|







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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
    chan close $f
    contents $path(test1)
} "a\x93\xe1\x00"
set path(test2) [makeFile {} test2]
test chan-io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug
    # applied to tcl will cause tcl, more specifically WriteChars, to
    # go into an infinite loop.

    set f [open $path(test2) w] 
    chan configure      $f -encoding iso2022-jp 
    chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399] 
    chan close           $f 
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"

test chan-io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends
    # escape bytes, check for the case where the escape
    # bytes overflow the current IO buffer. The bytes
    # should be moved into a new buffer.

    set data "1234567890 [format %c 12399]"

    set sizes [list]

    # With default buffer size
    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size equal to the length
    # of the data, the escape bytes would
    # go into the next buffer.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 16
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that is large enough
    # to hold 1 byte of escaped data, but
    # not all 3. This should not write
    # the escape bytes to the first buffer
    # and then again to the second buffer.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 17
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that can hold 2 out of
    # 3 bytes of escaped data.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 18
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    # With buffer size that can hold all the
    # data and escape bytes.

    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp -buffersize 19
    chan puts -nonewline $f $data
    chan close           $f
    lappend sizes [file size $path(test2)]

    set sizes
} {19 19 19 19 19}

test chan-io-2.1 {WriteBytes} {
    # loop until all bytes are written
    
    set f [open $path(test1) w]
    chan configure $f  -encoding binary -buffersize 16 -translation crlf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-2.2 {WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffersize 16 -translation crlf
    chan puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-2.3 {WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.
    
    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    set x [contents $path(test1)]

    chan close $f
    set x
} "\r\n12"
test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     chan configure $f -encoding binary -buffering line -translation lf \
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
    # loop until all bytes are written
    
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffersize 16 -translation crlf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffersize 16 -translation crlf
    chan puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.
    
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    set x [contents $path(test1)]

    chan close $f
    set x
} "\r\n12"
test chan-io-3.4 {WriteChars: loop over stage buffer} {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 16 
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.5 {WriteChars: saved != 0} {
    # Bytes produced by UtfToExternal from end of last channel buffer
    # had to be moved to beginning of next channel buffer to preserve
    # requested buffersize.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17 
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
    # One incomplete UTF-8 character at end of staging buffer.  Backup
    # in src to the beginning of that UTF-8 character and try again.
    #
    # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
    # (first two bytes of \uff21 in UTF-8).  Given those two bytes try
    # translating them again, find that no bytes are read produced, and break
    # to outer loop where those two bytes will have the remaining 4 bytes
    # (the last byte of \uff21 plus the all of \uff22) appended.

    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis -buffersize 16
    chan puts -nonewline $f "12345678901234\uff21\uff22"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
    # When translating UTF-8 to external, the produced bytes went past end
    # of the channel buffer.  This is done purpose -- we then truncate the
    # bytes at the end of the partial character to preserve the requested
    # blocksize on flush.  The truncated bytes are moved to the beginning
    # of the next channel buffer.

    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17 
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation lf \
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-4.1 {TranslateOutputEOL: lf} {
    # search for \n

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation lf
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\n" "abcde\n"]
test chan-io-4.2 {TranslateOutputEOL: cr} {
    # search for \n, replace with \r

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation cr
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\r" "abcde\r"]
test chan-io-4.3 {TranslateOutputEOL: crlf} {
    # simple case: search for \n, replace with \r

    set f [open $path(test1) w]
    chan configure $f -buffering line -translation crlf
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcde\r\n" "abcde\r\n"]
test chan-io-4.4 {TranslateOutputEOL: crlf} {
    # keep storing more bytes in output buffer until output buffer is full.
    # We have 13 bytes initially that would turn into 18 bytes.  Fill
    # dest buffer while (dstEnd < dstMax).

    set f [open $path(test1) w]
    chan configure $f -translation crlf -buffersize 16
    chan puts -nonewline $f "1234567\n\n\n\n\nA"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "1234567\r\n\r\n\r\n\r\n\r" "1234567\r\n\r\n\r\n\r\n\r\nA"]
test chan-io-4.5 {TranslateOutputEOL: crlf} {
    # Check for overflow of the destination buffer

    set f [open $path(test1) w]
    chan configure $f -translation crlf -buffersize 12
    chan puts -nonewline $f "12345678901\n456789012345678901234"
    chan close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test chan-io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    chan configure $f 
    chan puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test chan-io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400

401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436

437
438
439
440
441
442
443
444

445
446
447
448

449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493
    chan configure $f -buffering none
    chan puts -nonewline $f "1234567890"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "1234567890" "1234567890"]

test chan-io-6.1 {Tcl_GetsObj: working} -body {
    set f [open $path(test1) w]
    chan puts $f "foo\nboo"
    chan close $f
    set f [open $path(test1)]
    chan gets $f
} -cleanup {
    chan close $f

} -result {foo}
test chan-io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} emptyTest {
    # no test, need to cause an async error.
} {}
test chan-io-6.3 {Tcl_GetsObj: how many have we used?} -body {
    # if (bufPtr != NULL) {oldRemoved = bufPtr->nextRemoved}

    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts $f "abc\ndefg"
    chan close $f
    set f [open $path(test1)]
    list [chan tell $f] [chan gets $f line] [chan tell $f] [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result {0 3 5 4 defg}
test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} -body {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x81\u1234\0"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation binary
    list [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result [list 3 "\x81\x34\x00"]
test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} -body {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x88\xea\x92\x9a"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    list [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result [list 2 "\u4e00\u4e01"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test chan-io-6.6 {Tcl_GetsObj: loop test} -body {
    # if (dst >= dstEnd) 

    set f [open $path(test1) w]
    chan puts $f $a
    chan puts $f hi
    chan close $f
    set f [open $path(test1)]
    list [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result [list 256 $a]
test chan-io-6.7 {Tcl_GetsObj: error in input} -constraints {stdio openpipe} -body {
    # if (FilterInputBytes(chanPtr, &gs) != 0)
    set f [openpipe w+ $path(cat)]

    chan puts -nonewline $f "hi\nwould"
    chan flush $f
    chan gets $f
    chan configure $f -blocking 0
    chan gets $f line
} -cleanup {
    chan close $f

} -result {-1}
test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} -body {
    set f [open $path(test1) w]
    chan puts $f "abcdef\x1aghijk\nwombat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    list [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result {6 abcdef -1 {}}
test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} -body {
    set f [open $path(test1) w]
    chan puts $f "abcdefghijk\nwom\u001abat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    list [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result {11 abcdefghijk 3 wom}
# Comprehensive tests
test chan-io-6.10 {Tcl_GetsObj: lf mode: no chars} -body {
    set f [open $path(test1) w]
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation lf
    list [chan gets $f line] $line
} -cleanup {
    chan close $f

} -result {-1 {}}
test chan-io-6.11 {Tcl_GetsObj: lf mode: lone \n} {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "\n"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation lf







|




|
<

>
|



|

>





|
<

>
|
|






|
<

>
|
|






|
<

>
|



|

>





|
<

>
|
|

|
>




|
<

>
|
|





|
<

>
|
|





|
<

>
|

|




|
<

>
|







410
411
412
413
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526
    chan configure $f -buffering none
    chan puts -nonewline $f "1234567890"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "1234567890" "1234567890"]

test chan-io-6.1 {Tcl_GetsObj: working} {
    set f [open $path(test1) w]
    chan puts $f "foo\nboo"
    chan close $f
    set f [open $path(test1)]
    set x [chan gets $f]

    chan close $f
    set x
} {foo}
test chan-io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} emptyTest {
    # no test, need to cause an async error.
} {}
test chan-io-6.3 {Tcl_GetsObj: how many have we used?} {
    # if (bufPtr != NULL) {oldRemoved = bufPtr->nextRemoved}

    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts $f "abc\ndefg"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan tell $f] [chan gets $f line] [chan tell $f] [chan gets $f line] $line]

    chan close $f
    set x
} {0 3 5 4 defg}
test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x81\u1234\0"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation binary
    set x [list [chan gets $f line] $line]

    chan close $f
    set x
} [list 3 "\x81\x34\x00"]
test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x88\xea\x92\x9a"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    set x [list [chan gets $f line] $line]

    chan close $f
    set x
} [list 2 "\u4e00\u4e01"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test chan-io-6.6 {Tcl_GetsObj: loop test} {
    # if (dst >= dstEnd) 

    set f [open $path(test1) w]
    chan puts $f $a
    chan puts $f hi
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f line] $line]

    chan close $f
    set x
} [list 256 $a]
test chan-io-6.7 {Tcl_GetsObj: error in input} {stdio openpipe} {
    # if (FilterInputBytes(chanPtr, &gs) != 0)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan puts -nonewline $f "hi\nwould"
    chan flush $f
    chan gets $f
    chan configure $f -blocking 0
    set x [chan gets $f line]

    chan close $f
    set x
} {-1}
test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} {
    set f [open $path(test1) w]
    chan puts $f "abcdef\x1aghijk\nwombat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    set x [list [chan gets $f line] $line [chan gets $f line] $line]

    chan close $f
    set x
} {6 abcdef -1 {}}
test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} {
    set f [open $path(test1) w]
    chan puts $f "abcdefghijk\nwom\u001abat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    set x [list [chan gets $f line] $line [chan gets $f line] $line]

    chan close $f
    set x
} {11 abcdefghijk 3 wom}
# Comprehensive tests
test chan-io-6.10 {Tcl_GetsObj: lf mode: no chars} {
    set f [open $path(test1) w]
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation lf
    set x [list [chan gets $f line] $line]

    chan close $f
    set x
} {-1 {}}
test chan-io-6.11 {Tcl_GetsObj: lf mode: lone \n} {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "\n"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation lf
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan tell $f] [testchannel inputbuffered $f]]
    chan close $f
    set x
} [list 15 "123456789012345" 17 3]
test chan-io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} {
    # eol still equals dstEnd

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan eof $f]]
    chan close $f
    set x
} [list 16 "123456789012345\r" 1]
test chan-io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} {
    # not (*eol == '\n')

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\rabcd\r\nefg"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan tell $f]]







|











|
|







759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan tell $f] [testchannel inputbuffered $f]]
    chan close $f
    set x
} [list 15 "123456789012345" 17 3]
test chan-io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} {
    # eol still equals dstEnd
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan eof $f]]
    chan close $f
    set x
} [list 16 "123456789012345\r" 1]
test chan-io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} {
    # not (*eol == '\n') 
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\rabcd\r\nefg"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf -buffersize 16
    set x [list [chan gets $f line] $line [chan tell $f]]
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    set x [list [chan gets $f]]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan configure $f -blocking 1
    chan puts -nonewline $f "\nabcd\refg\x1a"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
    chan close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel openpipe fileevent} {
    # not (*eol == '\n')

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    set x [list [chan gets $f]]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan configure $f -blocking 1
    chan puts -nonewline $f "abcd\refg\x1a"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
    chan close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]







|








|







|







879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    set x [list [chan gets $f]]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f] 
    chan configure $f -blocking 1
    chan puts -nonewline $f "\nabcd\refg\x1a"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
    chan close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel openpipe fileevent} {
    # not (*eol == '\n') 

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    set x [list [chan gets $f]]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f] 
    chan configure $f -blocking 1
    chan puts -nonewline $f "abcd\refg\x1a"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
    chan close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
    chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -buffersize 16
    set x [list [chan gets $f] [testchannel inputbuffered $f]]
    chan close $f
    set x
} [list "123456789012345" 15]
test chan-io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} {testchannel} {
    # PeekAhead() did not get any, so (eol >= dstEnd)

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -buffersize 16
    set x [list [chan gets $f] [testchannel queuedcr $f]]
    chan close $f
    set x
} [list "123456789012345" 1]
test chan-io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} {testchannel} {
    # if (*eol == '\n') {skip++}

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\r\n78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
    chan close $f
    set x
} [list "123456" 0 8 "78901"]
test chan-io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} {testchannel} {
    # not (*eol == '\n')

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\r78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
    chan close $f
    set x
} [list "123456" 0 7 "78901"]
test chan-io-6.51 {Tcl_GetsObj: auto mode: \n} {
    # else if (*eol == '\n') {goto gotoeol;}

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\n78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [chan tell $f] [chan gets $f]]
    chan close $f







|


|












|










|
|











|







949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
    chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -buffersize 16
    set x [list [chan gets $f] [testchannel inputbuffered $f]]
    chan close $f
    set x
} [list "123456789012345" 15]    
test chan-io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} {testchannel} {
    # PeekAhead() did not get any, so (eol >= dstEnd)
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456789012345\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -buffersize 16
    set x [list [chan gets $f] [testchannel queuedcr $f]]
    chan close $f
    set x
} [list "123456789012345" 1]
test chan-io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} {testchannel} {
    # if (*eol == '\n') {skip++}
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\r\n78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
    chan close $f
    set x
} [list "123456" 0 8 "78901"]
test chan-io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} {testchannel} {
    # not (*eol == '\n') 
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\r78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
    chan close $f
    set x
} [list "123456" 0 7 "78901"]
test chan-io-6.51 {Tcl_GetsObj: auto mode: \n} {
    # else if (*eol == '\n') {goto gotoeol;}
    
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\n78901"
    chan close $f
    set f [open $path(test1)]
    set x [list [chan gets $f] [chan tell $f] [chan gets $f]]
    chan close $f
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
    chan configure $f -encoding shiftjis -buffersize 16
    set x [chan gets $f]
    chan close $f
    set x
} "1234567890123\uff10\uff11\uff12\uff13\uff14"
test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} {
    # (bufPtr->nextAdded < bufPtr->bufLength)

    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    set x [list [chan gets $f line] $line [chan eof $f]]







|







1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
    chan configure $f -encoding shiftjis -buffersize 16
    set x [chan gets $f]
    chan close $f
    set x
} "1234567890123\uff10\uff11\uff12\uff13\uff14"
test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} {
    # (bufPtr->nextAdded < bufPtr->bufLength)
    
    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    set x [list [chan gets $f line] $line [chan eof $f]]
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188

    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
    # is 30).  To check if "\n" follows, calls PeekAhead and determines
    # that cached data is available in buffer w/o having to call driver.

    set x [chan gets $f]
    chan close $f
    set x
} $a
unset a
test chan-io-8.5 {PeekAhead: don't peek if last read was short} {stdio testchannel openpipe fileevent} {
    # (bufPtr->nextAdded < bufPtr->length)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto binary}
    chan puts -nonewline $f "abcdefghijklmno\r"
    chan flush $f
    # here
    set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
    chan close $f
    set x
} {15 abcdefghijklmno 1}
test chan-io-8.6 {PeekAhead: change to non-blocking mode} {stdio testchannel openpipe fileevent} {
    # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto binary} -buffersize 16
    chan puts -nonewline $f "abcdefghijklmno\r"
    chan flush $f
    # here
    set x [list [chan gets $f line] $line [testchannel queuedcr $f]]







|















|







1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221

    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
    # is 30).  To check if "\n" follows, calls PeekAhead and determines
    # that cached data is available in buffer w/o having to call driver.

    set x [chan gets $f]
    chan close $f
    set x    
} $a
unset a
test chan-io-8.5 {PeekAhead: don't peek if last read was short} {stdio testchannel openpipe fileevent} {
    # (bufPtr->nextAdded < bufPtr->length)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto binary}
    chan puts -nonewline $f "abcdefghijklmno\r"
    chan flush $f
    # here
    set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
    chan close $f
    set x
} {15 abcdefghijklmno 1}
test chan-io-8.6 {PeekAhead: change to non-blocking mode} {stdio testchannel openpipe fileevent} {
    # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0) 

    set f [open "|[list [interpreter] $path(cat)]" w+]
    chan configure $f -translation {auto binary} -buffersize 16
    chan puts -nonewline $f "abcdefghijklmno\r"
    chan flush $f
    # here
    set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\n"
test chan-io-13.3 {TranslateInputEOL: crlf mode: naked cr} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\r"
test chan-io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\rfgh"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\rfgh"
test chan-io-13.5 {TranslateInputEOL: crlf mode: naked lf} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\nfgh"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf







|












|












|







1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\n"
test chan-io-13.3 {TranslateInputEOL: crlf mode: naked cr} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\r"
test chan-io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\rfgh"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef\rfgh"
test chan-io-13.5 {TranslateInputEOL: crlf mode: naked lf} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\r\ndef\nfgh"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation crlf
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
    set f [open $path(test1)]
    chan configure $f -translation auto
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef"
test chan-io-13.10 {TranslateInputEOL: auto mode: \n} {
    # not (*src == '\r')

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\ndef"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto







|







1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
    set f [open $path(test1)]
    chan configure $f -translation auto
    set x [chan read $f]
    chan close $f
    set x
} "abcd\ndef"
test chan-io-13.10 {TranslateInputEOL: auto mode: \n} {
    # not (*src == '\r') 

    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\ndef"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927

1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
    } else {
	lappend l "very broken: $f found after being chan closed"
    }
    string compare [string tolower $l] \
	[list 0 [format "can not find channel named \"%s\"" $f]]
} 0

test chan-io-20.1 {Tcl_CreateChannel: initial settings} -setup {
    set old [encoding system]
} -body {
    set a [open $path(test2) w]

    encoding system ascii
    set f [open $path(test1) w]
    chan configure $f -encoding
} -cleanup {
    encoding system $old
    chan close $f
    chan close $a
} -result {ascii}
test chan-io-20.2 {Tcl_CreateChannel: initial settings} -constraints {win} -body {
    set f [open $path(test1) w+]
    list [chan configure $f -eofchar] [chan configure $f -translation]
} -cleanup {
    chan close $f

} -result [list [list \x1a ""] {auto crlf}]
test chan-io-20.3 {Tcl_CreateChannel: initial settings} -constraints {unix} -body {
    set f [open $path(test1) w+]
    list [chan configure $f -eofchar] [chan configure $f -translation]
} -cleanup {
    chan close $f

} -result {{{} {}} {auto lf}}
test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} -setup {
    set path(stdout) [makeFile {} stdout]
} -constraints {stdio openpipe knownMsvcBug} -body {
    set f [open $path(script) w]
    chan puts -nonewline $f {
	chan close stdout
	set f1 [}
    chan puts $f [list open $path(stdout) w]]
    chan puts $f {
	chan configure $f1 -buffersize 777
	chan puts stderr [chan configure stdout -buffersize]
    }
    chan close $f
    set f [openpipe r $path(script)]
    chan close $f
} -cleanup {
    removeFile $path(stdout)
} -returnCodes error -result {777}

test chan-io-21.1 {Chan CloseChannelsOnExit} emptyTest {
} {}

# Test management of attributes associated with a channel, such as its default
# translation, its name and type, etc. The functions tested in this group are

# Tcl_GetChannelName, Tcl_GetChannelType and Tcl_GetChannelFile.
# Tcl_GetChannelInstanceData not tested because files do not use the instance
# data.

test chan-io-22.1 {Tcl_GetChannelMode} emptyTest {
    # Not used anywhere in Tcl.
} {}

test chan-io-23.1 {Tcl_GetChannelName} {testchannel} {
    file delete $path(test1)







|
<
<
|
>


|
|

|
|
|
|

|
<

>
|
|

|
<

>
|
<
|
|










|
|
|
<
|




|
|
>
|
|
<







1906
1907
1908
1909
1910
1911
1912
1913


1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932

1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
    } else {
	lappend l "very broken: $f found after being chan closed"
    }
    string compare [string tolower $l] \
	[list 0 [format "can not find channel named \"%s\"" $f]]
} 0

test chan-io-20.1 {Tcl_CreateChannel: initial settings} {


	set a [open $path(test2) w]
    set old [encoding system]
    encoding system ascii
    set f [open $path(test1) w]
    set x [chan configure $f -encoding]
    chan close $f
    encoding system $old
	chan close $a
    set x
} {ascii}    
test chan-io-20.2 {Tcl_CreateChannel: initial settings} {win} {
    set f [open $path(test1) w+]
    set x [list [chan configure $f -eofchar] [chan configure $f -translation]]

    chan close $f
    set x
} [list [list \x1a ""] {auto crlf}]
test chan-io-20.3 {Tcl_CreateChannel: initial settings} {unix} {
    set f [open $path(test1) w+]
    set x [list [chan configure $f -eofchar] [chan configure $f -translation]]

    chan close $f
    set x
} {{{} {}} {auto lf}}

set path(stdout) [makeFile {} stdout]
test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} {stdio openpipe} {
    set f [open $path(script) w]
    chan puts -nonewline $f {
	chan close stdout
	set f1 [}
    chan puts $f [list open $path(stdout) w]]
    chan puts $f {
	chan configure $f1 -buffersize 777
	chan puts stderr [chan configure stdout -buffersize]
    }
    chan close $f
    set f [open "|[list [interpreter] $path(script)]"]
    catch {chan close $f} msg
    set msg

} {777}

test chan-io-21.1 {Chan CloseChannelsOnExit} emptyTest {
} {}

# Test management of attributes associated with a channel, such as
# its default translation, its name and type, etc. The functions
# tested in this group are Tcl_GetChannelName,
# Tcl_GetChannelType and Tcl_GetChannelFile. Tcl_GetChannelInstanceData
# not tested because files do not use the instance data.


test chan-io-22.1 {Tcl_GetChannelMode} emptyTest {
    # Not used anywhere in Tcl.
} {}

test chan-io-23.1 {Tcl_GetChannelName} {testchannel} {
    file delete $path(test1)
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
test chan-io-26.1 {Tcl_GetChannelInstanceData} {stdio openpipe} {
    # "pid" command uses Tcl_GetChannelInstanceData
    # Don't care what pid is (but must be a number), just want to exercise it.

    set f [open "|[list [interpreter] << exit]"]
    expr [pid $f]
    chan close $f
} {}

# Test flushing. The functions tested here are FlushChannel.

test chan-io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan flush $f







|







2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
test chan-io-26.1 {Tcl_GetChannelInstanceData} {stdio openpipe} {
    # "pid" command uses Tcl_GetChannelInstanceData
    # Don't care what pid is (but must be a number), just want to exercise it.

    set f [open "|[list [interpreter] << exit]"]
    expr [pid $f]
    chan close $f
} {}    

# Test flushing. The functions tested here are FlushChannel.

test chan-io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan flush $f
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
    lappend l [file size $path(test1)]
    chan flush $f
    lappend l [file size $path(test1)]
    chan close $f
    set l
} {0 60 72}
test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} \
	{unixOrWin} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffersize 60 -eofchar {}
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	chan puts $f hello







|







2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
    lappend l [file size $path(test1)]
    chan flush $f
    lappend l [file size $path(test1)]
    chan close $f
    set l
} {0 60 72}
test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} \
	{unixOrPc} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffersize 60 -eofchar {}
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	chan puts $f hello
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
    }
    if {$counter == 1000} {
	set result "file size only [file size $path(output)]"
    } else {
	set result ok
    }
} ok
test chan-io-29.33 {Tcl_Flush, implicit flush on exit} -setup {
    set f [open $path(script) w]
    chan puts $f "set f \[[list open $path(test1) w]]"
    chan puts $f {chan configure $f -translation lf
	chan puts $f hello
	chan puts $f bye
	chan puts $f strange
    }
    chan close $f
} -constraints exec -body {
    exec [interpreter] $path(script)
    set f [open $path(test1) r]
    chan read $f
} -cleanup {
    chan close $f

} -result "hello\nbye\nstrange\n"
test chan-io-29.34 {Tcl_Chan Close, async flush on chan close, using sockets} -setup {
    variable c 0
    variable x running
    set l abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
    proc writelots {s l} {
	for {set i 0} {$i < 2000} {incr i} {
	    chan puts $s $l
	}
    }
} -constraints {socket tempNotMac fileevent knownMsvcBug} -body {
    proc accept {s a p} {
	variable x
	chan event $s readable [namespace code [list readit $s]]
	chan configure $s -blocking off
	set x accepted
    }
    proc readit {s} {
	variable c
	variable x
	set l [chan gets $s]

	if {[chan eof $s]} {
	    chan close $s
	    set x done
	} elseif {([string length $l] > 0) || ![chan blocked $s]} {
	    incr c
	}
    }
    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
    vwait [namespace which -variable x]
    chan configure $cs -blocking off
    writelots $cs $l
    chan close $cs
    chan close $ss
    vwait [namespace which -variable x]
    set c
} -result 2000
test chan-io-29.35 {Tcl_Chan Close vs chan event vs multiple interpreters} {socket tempNotMac fileevent} {
    # On Mac, this test screws up sockets such that subsequent tests using port 2828
    # either cause errors or panic().

    catch {interp delete x}
    catch {interp delete y}
    interp create x







|








<


|
<

>
|
|








<










>
















|







2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732

2733
2734
2735

2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
    }
    if {$counter == 1000} {
	set result "file size only [file size $path(output)]"
    } else {
	set result ok
    }
} ok
test chan-io-29.33 {Tcl_Flush, implicit flush on exit} {exec} {
    set f [open $path(script) w]
    chan puts $f "set f \[[list open $path(test1) w]]"
    chan puts $f {chan configure $f -translation lf
	chan puts $f hello
	chan puts $f bye
	chan puts $f strange
    }
    chan close $f

    exec [interpreter] $path(script)
    set f [open $path(test1) r]
    set r [chan read $f]

    chan close $f
    set r
} "hello\nbye\nstrange\n"
test chan-io-29.34 {Tcl_Chan Close, async flush on chan close, using sockets} {socket tempNotMac fileevent} {
    variable c 0
    variable x running
    set l abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
    proc writelots {s l} {
	for {set i 0} {$i < 2000} {incr i} {
	    chan puts $s $l
	}
    }

    proc accept {s a p} {
	variable x
	chan event $s readable [namespace code [list readit $s]]
	chan configure $s -blocking off
	set x accepted
    }
    proc readit {s} {
	variable c
	variable x
	set l [chan gets $s]

	if {[chan eof $s]} {
	    chan close $s
	    set x done
	} elseif {([string length $l] > 0) || ![chan blocked $s]} {
	    incr c
	}
    }
    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
    vwait [namespace which -variable x]
    chan configure $cs -blocking off
    writelots $cs $l
    chan close $cs
    chan close $ss
    vwait [namespace which -variable x]
    set c
} 2000
test chan-io-29.35 {Tcl_Chan Close vs chan event vs multiple interpreters} {socket tempNotMac fileevent} {
    # On Mac, this test screws up sockets such that subsequent tests using port 2828
    # either cause errors or panic().

    catch {interp delete x}
    catch {interp delete y}
    interp create x
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
    chan configure $f -translation cr
    chan puts $f hello\nthere\nand\nhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x
} "hello\rthere\rand\rhere\r"
test chan-io-30.7 {Tcl_Write crlf, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts $f hello\nthere\nand\nhere
    chan close $f







|







2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
    chan configure $f -translation cr
    chan puts $f hello\nthere\nand\nhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf
    set x [chan read $f]
    chan close $f
    set x 
} "hello\rthere\rand\rhere\r"
test chan-io-30.7 {Tcl_Write crlf, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts $f hello\nthere\nand\nhere
    chan close $f
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
    set line "123456789ABCDE"	;# 14 char plus crlf
    chan puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	chan puts $f $line
    }
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf
    set c ""
    while {[chan gets $f line] >= 0} {
	append c $line\n
    }
    chan close $f
    string length $c
} [expr 700*15+1]







|







3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
    set line "123456789ABCDE"	;# 14 char plus crlf
    chan puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	chan puts $f $line
    }
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf 
    set c ""
    while {[chan gets $f line] >= 0} {
	append c $line\n
    }
    chan close $f
    string length $c
} [expr 700*15+1]
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
    set x [chan configure $f -buffersize]
    chan close $f
    set x
} 40000
test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -encoding {}
    chan puts -nonewline $f \xe7\x89\xa6
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    set x [chan read $f]
    chan close $f
    set x







|







5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
    set x [chan configure $f -buffersize]
    chan close $f
    set x
} 40000
test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -encoding {} 
    chan puts -nonewline $f \xe7\x89\xa6
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    set x [chan read $f]
    chan close $f
    set x
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
    chan puts $f {copy_slowly $f}
    chan puts $f {exit}
    vwait [namespace which -variable x]
    chan close $f
    list $x $l
} {done {0 1 0 1 0 1 0 1 0 1 0 1 0 0}}
unset path(bar)
removeFile bar

test chan-io-48.4 {lf write, testing readability, ^Z termination, auto read mode} {fileevent} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation lf
    variable c [format "abc\ndef\n%c" 26]
    chan puts -nonewline $f $c







|







5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
    chan puts $f {copy_slowly $f}
    chan puts $f {exit}
    vwait [namespace which -variable x]
    chan close $f
    list $x $l
} {done {0 1 0 1 0 1 0 1 0 1 0 1 0 0}}
unset path(bar)
removeFile bar 

test chan-io-48.4 {lf write, testing readability, ^Z termination, auto read mode} {fileevent} {
    file delete $path(test1)
    set f [open $path(test1) w]
    chan configure $f -translation lf
    variable c [format "abc\ndef\n%c" 26]
    chan puts -nonewline $f $c
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898


6899
6900
6901
6902
6903
6904
6905
6906
	set fcopyTestDone 0
    } else {
        # Delay next chan copy to wait for size>0 input bytes
        after 100 [list chan copy $in $out -size 1000 \
		-command [namespace code [list doFcopy $in $out]]]
    }
}
test chan-io-53.7 {CopyData: Flooding chan copy from pipe} -setup {
    variable fcopyTestDone
    file delete $path(pipe)
    catch {unset fcopyTestDone}
} -constraints {stdio openpipe fcopy} -body {
    set fcopyTestCount 0
    set f1 [open $path(pipe) w]
    chan puts $f1 {
	# Write  10 bytes / 10 msec
	proc Write {count} {
	    chan puts -nonewline "1234567890"
	    if {[incr count -1]} {
	        after 10 [list Write $count]
	    } else {
	        set ::ready 1
	    }
	}
	chan configure stdout -buffering none
	Write 345 ;# 3450 bytes ~3.45 sec
	vwait ready
	exit 0
    }
    chan close $f1
    set in [openpipe r+ $path(pipe) &]
    set out [open $path(test1) w]
    doFcopy $in $out
    variable fcopyTestDone
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    # -1=error 0=script error N=number of bytes
    expr ($fcopyTestDone == 0) ? $fcopyTestCount : -1
} -cleanup {
    catch {chan close $in}
    chan close $out


} -result {3450}
test chan-io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
    # copy progress callback. errors out intentionally
    proc ::cmd args {
	lappend ::RES "CMD $args"
	error !STOP
    }
    # capture callback error here







|



<


















|



|


<
<
<


>
>
|







6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896

6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921



6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
	set fcopyTestDone 0
    } else {
        # Delay next chan copy to wait for size>0 input bytes
        after 100 [list chan copy $in $out -size 1000 \
		-command [namespace code [list doFcopy $in $out]]]
    }
}
test chan-io-53.7 {CopyData: Flooding chan copy from pipe} {stdio openpipe fcopy} {
    variable fcopyTestDone
    file delete $path(pipe)
    catch {unset fcopyTestDone}

    set fcopyTestCount 0
    set f1 [open $path(pipe) w]
    chan puts $f1 {
	# Write  10 bytes / 10 msec
	proc Write {count} {
	    chan puts -nonewline "1234567890"
	    if {[incr count -1]} {
	        after 10 [list Write $count]
	    } else {
	        set ::ready 1
	    }
	}
	chan configure stdout -buffering none
	Write 345 ;# 3450 bytes ~3.45 sec
	vwait ready
	exit 0
    }
    chan close $f1
    set in [open "|[list [interpreter] $path(pipe) &]" r+]
    set out [open $path(test1) w]
    doFcopy $in $out
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
	vwait [namespace which -variable fcopyTestDone]
    }



    catch {chan close $in}
    chan close $out
    # -1=error 0=script error N=number of bytes
    expr ($fcopyTestDone == 0) ? $fcopyTestCount : -1
} {3450}
test chan-io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
    # copy progress callback. errors out intentionally
    proc ::cmd args {
	lappend ::RES "CMD $args"
	error !STOP
    }
    # capture callback error here
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
	    chan close $sok
	}
	proc new {sok args} {
	    chan puts stderr NEW/$sok
	    global l srv
	    chan configure $sok -translation binary -buffering none
	    lappend l $sok
	    if {[llength $l] == 2} {
		chan close $srv
		foreach {a b} $l break
		chan copy $a $b -command [list geof $a]
		chan copy $b $a -command [list geof $b]
		chan puts stderr 2COPY
	    }
	    chan puts stderr ...







|







7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
	    chan close $sok
	}
	proc new {sok args} {
	    chan puts stderr NEW/$sok
	    global l srv
	    chan configure $sok -translation binary -buffering none
	    lappend l $sok
	    if {[llength $l]==2} {
		chan close $srv
		foreach {a b} $l break
		chan copy $a $b -command [list geof $a]
		chan copy $b $a -command [list geof $b]
		chan puts stderr 2COPY
	    }
	    chan puts stderr ...
7102
7103
7104
7105
7106
7107
7108

7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126

7127
7128

7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
    removeFile err
    catch {unset ::forever}
} -result {AB BA}

test chan-io-54.1 {Recursive channel events} {socket fileevent} {
    # This test checks to see if file events are delivered during recursive
    # event loops when there is buffered data on the channel.

    proc accept {s a p} {
	variable as
	chan configure $s -translation lf
	chan puts $s "line 1\nline2\nline3"
	chan flush $s
	set as $s
    }
    proc readit {s next} {
	variable x
	variable result
	lappend result $next
	if {$next == 1} {
	    chan event $s readable [namespace code [list readit $s 2]]
	    vwait [namespace which -variable x]
	}
	incr x
    }
    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]

    # We need to delay on some systems until the creation of the server socket
    # completes.

    set done 0
    for {set i 0} {$i < 10} {incr i} {
	if {![catch {
	    set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
	}]} {
	    set done 1
	    break
	}
	after 100
    }
    if {$done == 0} {
	chan close $ss







>


















>
|
|
>


<
|
<







7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160

7161

7162
7163
7164
7165
7166
7167
7168
    removeFile err
    catch {unset ::forever}
} -result {AB BA}

test chan-io-54.1 {Recursive channel events} {socket fileevent} {
    # This test checks to see if file events are delivered during recursive
    # event loops when there is buffered data on the channel.

    proc accept {s a p} {
	variable as
	chan configure $s -translation lf
	chan puts $s "line 1\nline2\nline3"
	chan flush $s
	set as $s
    }
    proc readit {s next} {
	variable x
	variable result
	lappend result $next
	if {$next == 1} {
	    chan event $s readable [namespace code [list readit $s 2]]
	    vwait [namespace which -variable x]
	}
	incr x
    }
    set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]

    # We need to delay on some systems until the creation of the
    # server socket completes.

    set done 0
    for {set i 0} {$i < 10} {incr i} {

	if {![catch {set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]}]} {

	    set done 1
	    break
	}
	after 100
    }
    if {$done == 0} {
	chan close $ss
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167



7168
7169
7170
7171
7172
7173

7174
7175

7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186

7187
7188
7189
7190
7191
7192
7193
7194

7195
7196
7197
7198
7199








7200

7201
7202
7203
7204

7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
    vwait [namespace which -variable x]
    after cancel $a
    chan close $as
    chan close $ss
    chan close $cs
    list $result $x
} {{{line 1} 1 2} 2}
test chan-io-54.2 {Testing for busy-wait in recursive channel events} -setup {
    set accept {}
    set after {}
    variable done 0
} -constraints {socket fileevent} -body {
    variable s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    proc accept {s a p} {
	variable counter 0
	variable accept $s



	chan configure $s -blocking off -buffering line -translation lf
	chan event $s readable [namespace code "doit $s"]
    }
    proc doit {s} {
	variable counter
	variable after

	incr counter
	if {[chan gets $s] eq ""} {

	    chan event $s readable [namespace code "doit1 $s"]
	    set after [after 1000 [namespace code {
		chan puts $writer hello
		chan flush $writer
		set done 1
	    }]]
	}
    }
    proc doit1 {s} {
	variable counter
	variable accept

	incr counter
	chan gets $s
	chan close $s
	set accept {}
    }
    proc producer {} {
	variable s
	variable writer

	set writer [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
	chan configure $writer -buffering line
	chan puts -nonewline $writer hello
	chan flush $writer
    }








    producer

    vwait [namespace which -variable done]
    chan close $writer
    chan close $s
    after cancel $after

    set counter
} -cleanup {
    if {$accept != {}} {chan close $accept}
} -result 1

set path(fooBar) [makeFile {} fooBar]

test chan-io-55.1 {ChannelEventScriptInvoker: deletion} -constraints {
    fileevent
} -setup {
    variable x







|


<
<


|
|
>
>
>






>

|
>

|
<
<
<
<





>

|






>





>
>
>
>
>
>
>
>

>




>

|
<
<







7180
7181
7182
7183
7184
7185
7186
7187
7188
7189


7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208




7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245


7246
7247
7248
7249
7250
7251
7252
    vwait [namespace which -variable x]
    after cancel $a
    chan close $as
    chan close $ss
    chan close $cs
    list $result $x
} {{{line 1} 1 2} 2}
test chan-io-54.2 {Testing for busy-wait in recursive channel events} {socket fileevent} {
    set accept {}
    set after {}


    variable s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    proc accept {s a p} {
	variable counter
	variable accept

	set accept $s
	set counter 0
	chan configure $s -blocking off -buffering line -translation lf
	chan event $s readable [namespace code "doit $s"]
    }
    proc doit {s} {
	variable counter
	variable after

	incr counter
	set l [chan gets $s]
	if {"$l" == ""} {
	    chan event $s readable [namespace code "doit1 $s"]
	    set after [after 1000 [namespace code newline]]




	}
    }
    proc doit1 {s} {
	variable counter
	variable accept

	incr counter
	set l [chan gets $s]
	chan close $s
	set accept {}
    }
    proc producer {} {
	variable s
	variable writer

	set writer [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
	chan configure $writer -buffering line
	chan puts -nonewline $writer hello
	chan flush $writer
    }
    proc newline {} {
	variable done
	variable writer

	chan puts $writer hello
	chan flush $writer
	set done 1
    }
    producer
    variable done
    vwait [namespace which -variable done]
    chan close $writer
    chan close $s
    after cancel $after
    if {$accept != {}} {chan close $accept}
    set counter
} 1



set path(fooBar) [makeFile {} fooBar]

test chan-io-55.1 {ChannelEventScriptInvoker: deletion} -constraints {
    fileevent
} -setup {
    variable x
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266

7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281

7282
7283
7284
7285
7286
7287
7288
7289
7290
7291

7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306

7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340


7341
7342
7343
7344
7345
7346
7347
7348

7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370

7371
7372
7373
7374
7375
7376
7377
    after idle [namespace code {set y done}]
    variable y
    vwait [namespace which -variable y]
    chan close $f
    lappend result $y
} {2 done}

test chan-io-57.1 {buffered data and file events, gets} -setup {
    variable s2
} -constraints {fileevent} -body {
    proc accept {sock args} {
	variable s2
	set s2 $sock
    }
    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]

    vwait [namespace which -variable s2]
    update
    chan event $s2 readable [namespace code {lappend result readable}]
    chan puts $s "12\n34567890"
    chan flush $s
    variable result [chan gets $s2]
    after 1000 [namespace code {lappend result timer}]
    vwait [namespace which -variable result]
    lappend result [chan gets $s2]
    vwait [namespace which -variable result]
    set result
} -cleanup {
    chan close $s
    chan close $s2
    chan close $server

} -result {12 readable 34567890 timer}
test chan-io-57.2 {buffered data and file events, read} -setup {
    variable s2
} -constraints {fileevent} -body {
    proc accept {sock args} {
	variable s2
	set s2 $sock
    }
    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]

    vwait [namespace which -variable s2]
    update
    chan event $s2 readable [namespace code {lappend result readable}]
    chan puts -nonewline $s "1234567890"
    chan flush $s
    variable result [chan read $s2 1]
    after 1000 [namespace code {lappend result timer}]
    vwait [namespace which -variable result]
    lappend result [chan read $s2 9]
    vwait [namespace which -variable result]
    set result
} -cleanup {
    chan close $s
    chan close $s2
    chan close $server

} -result {1 readable 234567890 timer}

test chan-io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrWin openpipe fileevent} {
    set out [open $path(script) w]
    chan puts $out {
	chan puts "normal message from pipe"
	chan puts stderr "error message from pipe"
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]
	    lappend result catch $line
	} else {
	    chan gets $pipe line
	    lappend result chan gets $line
	}
    }
    chan close $out
    set pipe [openpipe r $path(script)]
    chan event $pipe readable [namespace code [list readit $pipe]]
    variable x ""
    set result ""
    vwait [namespace which -variable x]
    list $x $result
} {1 {chan gets {normal message from pipe} chan gets {} catch {error message from pipe}}}

test chan-io-59.1 {Thread reference of channels} {testmainthread testchannel} {
    # TIP #10
    # More complicated tests (like that the reference changes as a channel is
    # moved from thread to thread) can be done only in the extension which
    # fully implements the moving of channels between threads, i.e. 'Threads'.


    set f [open $path(longfile) r]
    set result [testchannel mthread $f]
    chan close $f
    string equal $result [testmainthread]
} {1}

test chan-io-60.1 {writing illegal utf sequences} {openpipe fileevent} {
    # This test will hang in older revisions of the core.

    set out [open $path(script) w]
    chan puts $out {
	chan puts [encoding convertfrom identity \xe2]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]
	    lappend result catch $line
	} else {
	    chan gets $pipe line
	    lappend result gets $line
	}
    }
    chan close $out
    set pipe [openpipe r $path(script)]
    chan event $pipe readable [namespace code [list readit $pipe]]
    variable x ""
    set result ""
    vwait [namespace which -variable x]

    # cut of the remainder of the error stack, especially the filename
    set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
    list $x $result
} {1 {gets {} catch {error writing "stdout": invalid argument}}}

test chan-io-61.1 {Reset eof state after changing the eof char} -setup {
    set datafile [makeFile {} eofchar]







|
<
<






>










<
<



>
|
|
<
<






>










<
<



>
|

|


















|









|
|
|
>
>








>

















|




>







7288
7289
7290
7291
7292
7293
7294
7295


7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312


7313
7314
7315
7316
7317
7318


7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335


7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
    after idle [namespace code {set y done}]
    variable y
    vwait [namespace which -variable y]
    chan close $f
    lappend result $y
} {2 done}

test chan-io-57.1 {buffered data and file events, gets} {fileevent} {


    proc accept {sock args} {
	variable s2
	set s2 $sock
    }
    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
    variable s2
    vwait [namespace which -variable s2]
    update
    chan event $s2 readable [namespace code {lappend result readable}]
    chan puts $s "12\n34567890"
    chan flush $s
    variable result [chan gets $s2]
    after 1000 [namespace code {lappend result timer}]
    vwait [namespace which -variable result]
    lappend result [chan gets $s2]
    vwait [namespace which -variable result]


    chan close $s
    chan close $s2
    chan close $server
    set result
} {12 readable 34567890 timer}
test chan-io-57.2 {buffered data and file events, read} {fileevent} {


    proc accept {sock args} {
	variable s2
	set s2 $sock
    }
    set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
    variable s2
    vwait [namespace which -variable s2]
    update
    chan event $s2 readable [namespace code {lappend result readable}]
    chan puts -nonewline $s "1234567890"
    chan flush $s
    variable result [chan read $s2 1]
    after 1000 [namespace code {lappend result timer}]
    vwait [namespace which -variable result]
    lappend result [chan read $s2 9]
    vwait [namespace which -variable result]


    chan close $s
    chan close $s2
    chan close $server
    set result
} {1 readable 234567890 timer}

test chan-io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrPc openpipe fileevent} {
    set out [open $path(script) w]
    chan puts $out {
	chan puts "normal message from pipe"
	chan puts stderr "error message from pipe"
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]
	    lappend result catch $line
	} else {
	    chan gets $pipe line
	    lappend result chan gets $line
	}
    }
    chan close $out
    set pipe [open "|[list [interpreter] $path(script)]" r]
    chan event $pipe readable [namespace code [list readit $pipe]]
    variable x ""
    set result ""
    vwait [namespace which -variable x]
    list $x $result
} {1 {chan gets {normal message from pipe} chan gets {} catch {error message from pipe}}}

test chan-io-59.1 {Thread reference of channels} {testmainthread testchannel} {
    # TIP #10
    # More complicated tests (like that the reference changes as a
    # channel is moved from thread to thread) can be done only in the
    # extension which fully implements the moving of channels between
    # threads, i.e. 'Threads'. Or we have to extend [testthread] as well.

    set f [open $path(longfile) r]
    set result [testchannel mthread $f]
    chan close $f
    string equal $result [testmainthread]
} {1}

test chan-io-60.1 {writing illegal utf sequences} {openpipe fileevent} {
    # This test will hang in older revisions of the core.

    set out [open $path(script) w]
    chan puts $out {
	chan puts [encoding convertfrom identity \xe2]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]
	    lappend result catch $line
	} else {
	    chan gets $pipe line
	    lappend result gets $line
	}
    }
    chan close $out
    set pipe [open "|[list [interpreter] $path(script)]" r]
    chan event $pipe readable [namespace code [list readit $pipe]]
    variable x ""
    set result ""
    vwait [namespace which -variable x]

    # cut of the remainder of the error stack, especially the filename
    set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
    list $x $result
} {1 {gets {} catch {error writing "stdout": invalid argument}}}

test chan-io-61.1 {Reset eof state after changing the eof char} -setup {
    set datafile [makeFile {} eofchar]
7390
7391
7392
7393
7394
7395
7396
7397
7398


7399
7400
7401

7402
7403
7404
7405
7406
7407
7408
7409
7410
7411


7412
7413

7414
7415

7416
7417
7418

7419


7420
7421
7422
7423
7424
7425
7426
7427
    chan configure $f -eofchar {}
    lappend res [chan read $f 1]
    lappend res [chan read $f; chan tell $f]
    # Any seek zaps the internals into a good state.
    #chan seek $f 0 start
    #chan seek $f 0 current
    #lappend res [chan read $f; chan tell $f]
} -cleanup {
    chan close $f


    removeFile eofchar
} -result {77 = 23431}


# Test the cutting and splicing of channels, this is incidentially the
# attach/detach facility of package Thread, but __without any safeguards__. It
# can also be used to emulate transfer of channels between threads, and is
# used for that here.

test chan-io-70.0 {Cutting & Splicing channels} -setup {
    set f [makeFile {... dummy ...} cutsplice]
    set res {}
} -constraints {testchannel} -body {
    set c [open $f r]


    lappend res [catch {chan seek $c 0 start}]
    testchannel cut $c

    lappend res [catch {chan seek $c 0 start}]
    testchannel splice $c

    lappend res [catch {chan seek $c 0 start}]
} -cleanup {
    chan close $c

    removeFile cutsplice


} -result {0 1 0}


# Duplicate of code in "thread.test". Find a better way of doing this
# without duplication. Maybe placement into a proc which transforms to
# nop after the first call, and placement of its defintion in a
# central location.








<

>
>



>

|
|
|

|

<
<

>
>


>


>

<

>

>
>
|







7427
7428
7429
7430
7431
7432
7433

7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447


7448
7449
7450
7451
7452
7453
7454
7455
7456
7457

7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
    chan configure $f -eofchar {}
    lappend res [chan read $f 1]
    lappend res [chan read $f; chan tell $f]
    # Any seek zaps the internals into a good state.
    #chan seek $f 0 start
    #chan seek $f 0 current
    #lappend res [chan read $f; chan tell $f]

    chan close $f
    set res
} -cleanup {
    removeFile eofchar
} -result {77 = 23431}


# Test the cutting and splicing of channels, this is incidentially the
# attach/detach facility of package Thread, but __without any
# safeguards__. It can also be used to emulate transfer of channels
# between threads, and is used for that here.

test chan-io-70.0 {Cutting & Splicing channels} {testchannel} {
    set f [makeFile {... dummy ...} cutsplice]


    set c [open $f r]

    set     res {}
    lappend res [catch {chan seek $c 0 start}]
    testchannel cut $c

    lappend res [catch {chan seek $c 0 start}]
    testchannel splice $c

    lappend res [catch {chan seek $c 0 start}]

    chan close $c

    removeFile cutsplice

    set res
} {0 1 0}


# Duplicate of code in "thread.test". Find a better way of doing this
# without duplication. Maybe placement into a proc which transforms to
# nop after the first call, and placement of its defintion in a
# central location.

7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667

test chan-io-73.1 {channel Tcl_Obj SetChannelFromAny} {} {
    # Test for Bug 1847044 - don't spoil type unless we have a valid channel
    catch {chan close [lreplace [list a] 0 end]}
} {1}

# ### ### ### ######### ######### #########

# cleanup
foreach file [list fooBar longfile script output test1 pipe my_script \
	test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
    removeFile $file
}
cleanupTests
}
namespace delete ::tcl::test::io







|








7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710

test chan-io-73.1 {channel Tcl_Obj SetChannelFromAny} {} {
    # Test for Bug 1847044 - don't spoil type unless we have a valid channel
    catch {chan close [lreplace [list a] 0 end]}
} {1}

# ### ### ### ######### ######### #########

# cleanup
foreach file [list fooBar longfile script output test1 pipe my_script \
	test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
    removeFile $file
}
cleanupTests
}
namespace delete ::tcl::test::io

Changes to tests/clock.test.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]

if {[namespace which -command ::tcl::unsupported::timerate] ne ""} {
    namespace import ::tcl::unsupported::timerate
}

# TEST PLAN

# clock-1:
#	[clock format] - tests of bad and empty arguments 
#
# clock-2 
#	formatting of year, month and day of month







<
<
<
<







28
29
30
31
32
33
34




35
36
37
38
39
40
41
package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]





# TEST PLAN

# clock-1:
#	[clock format] - tests of bad and empty arguments 
#
# clock-2 
#	formatting of year, month and day of month
35024
35025
35026
35027
35028
35029
35030
35031
35032
35033
35034
35035
35036
35037
35038
35039
35040
35041
35042
35043
35044
35045
35046
35047
35048
35049
35050
35051
35052
35053
35054
35055
    set f4 [clock add $t -4 month -timezone :UTC]
    set x1 [clock format $f1 -format %Y-%m-%d -timezone :UTC]
    set x2 [clock format $f2 -format %Y-%m-%d -timezone :UTC]
    set x3 [clock format $f3 -format %Y-%m-%d -timezone :UTC]
    set x4 [clock format $f4 -format %Y-%m-%d -timezone :UTC]
    list $x1 $x2 $x3 $x4
} {2000-02-29 2000-01-31 1999-12-31 1999-11-30}
test clock-30.8a {clock add months, negative, over threshold of a year} {
    set t [clock scan 2019-01-31 -format %Y-%m-%d -gmt 1]
    list [clock format [clock add $t -1 month -gmt 1] -format %Y-%m-%d -gmt 1] \
	 [clock format [clock add $t -2 month -gmt 1] -format %Y-%m-%d -gmt 1] \
	 [clock format [clock add $t -3 month -gmt 1] -format %Y-%m-%d -gmt 1] \
	 [clock format [clock add $t -4 month -gmt 1] -format %Y-%m-%d -gmt 1]
} {2018-12-31 2018-11-30 2018-10-31 2018-09-30}
test clock-30.8b {clock add months, negative, over threshold of a year} {
    set t [clock scan 2000-01-28 -format %Y-%m-%d -gmt 1]
    for {set i 1} {$i < 24} {incr i 1} {
	set f1 [clock add $t -$i month -gmt 1]
	set f2 [clock add $f1 $i month -gmt 1]
	if {$f2 != $t} {
	    error "\[clock add $t -$i month -gmt 1\] does not consider\
		   \[clock add $f1 $i month -gmt 1\] != $t"
	}
    }
} {}
test clock-30.9 {clock add days} {
    set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
	       -timezone :UTC]
    set f1 [clock add $t 1 day -timezone :UTC]
    set f2 [clock add $t -1 day -timezone :UTC]
    set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
    set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







35020
35021
35022
35023
35024
35025
35026


















35027
35028
35029
35030
35031
35032
35033
    set f4 [clock add $t -4 month -timezone :UTC]
    set x1 [clock format $f1 -format %Y-%m-%d -timezone :UTC]
    set x2 [clock format $f2 -format %Y-%m-%d -timezone :UTC]
    set x3 [clock format $f3 -format %Y-%m-%d -timezone :UTC]
    set x4 [clock format $f4 -format %Y-%m-%d -timezone :UTC]
    list $x1 $x2 $x3 $x4
} {2000-02-29 2000-01-31 1999-12-31 1999-11-30}


















test clock-30.9 {clock add days} {
    set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
	       -timezone :UTC]
    set f1 [clock add $t 1 day -timezone :UTC]
    set f2 [clock add $t -1 day -timezone :UTC]
    set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
    set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
35459
35460
35461
35462
35463
35464
35465
35466
35467
35468

35469
35470
35471
35472
35473
35474
35475
35476
35477
35478
35479
35480
35481
35482
35483
35484

35485
35486
35487
35488
35489
35490
35491
35492
35493
35494
35495
35496
35497
35498
35499
35500
35501
35502
35503
35504
35505
35506
35507

35508
35509
35510
35511
35512
35513
35514
35515
35516
35517
35518
35519

35520
35521
35522
35523
35524
35525
35526
35527
35528
35529
35530
test clock-33.4a {clock milliseconds} {
    expr { [clock milliseconds] + 1 }
    concat {}
} {}
test clock-33.5 {clock clicks tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock clicks -milli]
	timerate {} 10; # short but precise busy wait

	set end [clock clicks -milli]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" : 
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.5a {clock tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock milliseconds]
	timerate {} 10; # short but precise busy wait

	set end [clock milliseconds]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" : 
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.6 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks ? } msg] $msg
} {1 {bad option "?": must be -milliseconds or -microseconds}}
test clock-33.7 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks - } msg] $msg
} {1 {ambiguous option "-": must be -milliseconds or -microseconds}}

test clock-33.8 {clock clicks test, microsecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock clicks -micro]
	timerate {} 10; # short but precise busy wait

	set end [clock clicks -micro]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    expr {($end > $start) && (($end - $start) <= 60000)}
} {1}
test clock-33.8a {clock test, microsecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock microseconds]
	timerate {} 10; # short but precise busy wait

	set end [clock microseconds]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    expr {($end > $start) && (($end - $start) <= 60000)}
} {1}

test clock-33.9 {clock clicks test, millis align with seconds} {
    set t1 [clock seconds]
    while { 1 } {
	set t2 [clock clicks -millis]







<
|
<
>
|
<
<
<









<
|
<
>
|
<
<
<
















<
|
<
>
|
<
<
<





<
|
<
>
|
<
<
<







35437
35438
35439
35440
35441
35442
35443

35444

35445
35446



35447
35448
35449
35450
35451
35452
35453
35454
35455

35456

35457
35458



35459
35460
35461
35462
35463
35464
35465
35466
35467
35468
35469
35470
35471
35472
35473
35474

35475

35476
35477



35478
35479
35480
35481
35482

35483

35484
35485



35486
35487
35488
35489
35490
35491
35492
test clock-33.4a {clock milliseconds} {
    expr { [clock milliseconds] + 1 }
    concat {}
} {}
test clock-33.5 {clock clicks tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.

    set start [clock clicks -milli]

    after 10
    set end [clock clicks -milli]



    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" : 
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.5a {clock tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.

    set start [clock milliseconds]

    after 10
    set end [clock milliseconds]



    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" : 
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.6 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks ? } msg] $msg
} {1 {bad option "?": must be -milliseconds or -microseconds}}
test clock-33.7 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks - } msg] $msg
} {1 {ambiguous option "-": must be -milliseconds or -microseconds}}

test clock-33.8 {clock clicks test, microsecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.

    set start [clock clicks -micro]

    after 10
    set end [clock clicks -micro]



    expr {($end > $start) && (($end - $start) <= 60000)}
} {1}
test clock-33.8a {clock test, microsecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.

    set start [clock microseconds]

    after 10
    set end [clock microseconds]



    expr {($end > $start) && (($end - $start) <= 60000)}
} {1}

test clock-33.9 {clock clicks test, millis align with seconds} {
    set t1 [clock seconds]
    while { 1 } {
	set t2 [clock clicks -millis]
36733
36734
36735
36736
36737
36738
36739
36740
36741
36742
36743
36744
36745
36746
36747
36748
36749
36750
36751
36752
36753
36754
36755
36756
36757
36758
		}
	    }
	    return $retval
	}
    }
    -body {
	set trouble {}
	foreach {date jdate} {
	    1872-12-31 \u897f\u66a61872\u5e7412\u670831\u65e5
	    1873-01-01 \u660e\u6cbb06\u5e7401\u670801\u65e5
	    1912-07-29 \u660e\u6cbb45\u5e7407\u670829\u65e5
	    1912-07-30 \u5927\u6b6301\u5e7407\u670830\u65e5
	    1926-12-24 \u5927\u6b6315\u5e7412\u670824\u65e5
	    1926-12-25 \u662d\u548c01\u5e7412\u670825\u65e5
	    1989-01-07 \u662d\u548c64\u5e7401\u670807\u65e5
	    1989-01-08 \u5e73\u621001\u5e7401\u670808\u65e5
	    2019-04-30 \u5e73\u621031\u5e7404\u670830\u65e5
	    2019-05-01 \u4ee4\u548c01\u5e7405\u670801\u65e5
	} {
	    set status [catch {
		set secs [clock scan $date \
			      -timezone +0900 \
			      -locale ja_JP \
			      -format %Y-%m-%d]
		set jda [clock format $secs \
			     -timezone +0900 \







|
|
|
|
|
|
|
|
|
<
<
|







36695
36696
36697
36698
36699
36700
36701
36702
36703
36704
36705
36706
36707
36708
36709
36710


36711
36712
36713
36714
36715
36716
36717
36718
		}
	    }
	    return $retval
	}
    }
    -body {
	set trouble {}
	foreach {date jdate} [list \
	    1872-12-31 \u897f\u66a61872\u5e7412\u670831\u65e5 \
	    1873-01-01 \u660e\u6cbb06\u5e7401\u670801\u65e5 \
	    1912-07-29 \u660e\u6cbb45\u5e7407\u670829\u65e5 \
	    1912-07-30 \u5927\u6b6301\u5e7407\u670830\u65e5 \
	    1926-12-24 \u5927\u6b6315\u5e7412\u670824\u65e5 \
	    1926-12-25 \u662d\u548c01\u5e7412\u670825\u65e5 \
	    1989-01-07 \u662d\u548c64\u5e7401\u670807\u65e5 \
	    1989-01-08 \u5e73\u621001\u5e7401\u670808\u65e5 \


	] {
	    set status [catch {
		set secs [clock scan $date \
			      -timezone +0900 \
			      -locale ja_JP \
			      -format %Y-%m-%d]
		set jda [clock format $secs \
			     -timezone +0900 \

Changes to tests/cmdAH.test.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testchmod       [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype  [llength [info commands testvolumetype]]
testConstraint time64bit [expr {
    $::tcl_platform(pointerSize) >= 8 ||
    [llength [info command testsize]] && [testsize st_mtime] >= 8
}]
testConstraint linkDirectory [expr {
    ![testConstraint win] ||
    ($::tcl_platform(osVersion) >= 5.0
     && [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]

global env
set cmdAHwd [pwd]
catch {set platform [testgetplatform]}








<
<
<
<


|







14
15
16
17
18
19
20




21
22
23
24
25
26
27
28
29
30
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testchmod       [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype  [llength [info commands testvolumetype]]




testConstraint linkDirectory [expr {
    ![testConstraint win] ||
    ([string index $tcl_platform(osVersion) 0] >= 5
     && [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]

global env
set cmdAHwd [pwd]
catch {set platform [testgetplatform]}

368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
    set result
} {0 ~}
test cmdAH-8.45 {Tcl_FileObjCmd: dirname} {
    -constraints {win testsetplatform}
    -match regexp
    -setup {
	set temp $::env(HOME)
    }
    -body {
	set ::env(HOME) "/homewontexist/test"
	testsetplatform windows
	file dirname ~
    }
    -cleanup {
	set ::env(HOME) $temp







|







364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
    set result
} {0 ~}
test cmdAH-8.45 {Tcl_FileObjCmd: dirname} {
    -constraints {win testsetplatform}
    -match regexp
    -setup {
	set temp $::env(HOME)
    }	
    -body {
	set ::env(HOME) "/homewontexist/test"
	testsetplatform windows
	file dirname ~
    }
    -cleanup {
	set ::env(HOME) $temp
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
    testsetplatform windows
    file tail {c:/foo\bar}
} bar
test cmdAH-9.51 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform windows
    file tail {foo\bar}
} bar
test cmdAH-9.52 {Tcl_FileObjCmd: tail / normalize, bug 7a9dc52b29} {
    list \
	[file tail {~/~foo}] \
	[file tail {~/test/~foo}] \
	[file tail [file normalize {~/~foo}]] \
	[file tail [file normalize {~/test/~foo}]]
} [lrepeat 4 ./~foo]

# rootname

test cmdAH-10.1 {Tcl_FileObjCmd: rootname} testsetplatform {
    testsetplatform unix
    list [catch {file rootname a b} msg] $msg
} {1 {wrong # args: should be "file rootname name"}}







<
<
<
<
<
<
<







537
538
539
540
541
542
543







544
545
546
547
548
549
550
    testsetplatform windows
    file tail {c:/foo\bar}
} bar
test cmdAH-9.51 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform windows
    file tail {foo\bar}
} bar








# rootname

test cmdAH-10.1 {Tcl_FileObjCmd: rootname} testsetplatform {
    testsetplatform unix
    list [catch {file rootname a b} msg] $msg
} {1 {wrong # args: should be "file rootname name"}}
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
    # cause that file to be executable.

    testchmod 0775 $gorpfile
    file exe $gorpfile
} 1

test cmdAH-18.5 {Tcl_FileObjCmd: executable} {win} {
    # On windows, must be a .exe, .com, etc.

    set x [file exe $gorpfile]
    set gorpexe [makeFile foo gorp.exe]
    lappend x [file exe $gorpexe]
    removeFile $gorpexe
    set x
} {0 1}
test cmdAH-18.5.1 {Tcl_FileObjCmd: executable} {win} {
    # On windows, must be a .exe, .com, etc.

    set x [file exe $gorpfile]
    set gorpexe [makeFile foo gorp.exe]
    lappend x [file exe [string toupper $gorpexe]]
    removeFile $gorpexe
    set x
} {0 1}







|








|







863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
    # cause that file to be executable.

    testchmod 0775 $gorpfile
    file exe $gorpfile
} 1

test cmdAH-18.5 {Tcl_FileObjCmd: executable} {win} {
    # On pc, must be a .exe, .com, etc.

    set x [file exe $gorpfile]
    set gorpexe [makeFile foo gorp.exe]
    lappend x [file exe $gorpexe]
    removeFile $gorpexe
    set x
} {0 1}
test cmdAH-18.5.1 {Tcl_FileObjCmd: executable} {win} {
    # On pc, must be a .exe, .com, etc.

    set x [file exe $gorpfile]
    set gorpexe [makeFile foo gorp.exe]
    lappend x [file exe [string toupper $gorpexe]]
    removeFile $gorpexe
    set x
} {0 1}
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
    file mtime $dirname 0
    set new [file mtime $dirname]
    list $new [expr {$old != $new}]
} -cleanup {
    file delete -force $dirname
} -result {0 1}

# 3155760000 is 64-bit unix time, Wed Jan 01 00:00:00 GMT 2070:
test cmdAH-24.20.1 {Tcl_FileObjCmd: atime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit} -setup {
    set filename [makeFile "" foo.text]
} -body {
    list [file atime $filename 3155760000] [file atime $filename]
} -cleanup {
    removeFile $filename
} -result {3155760000 3155760000}
test cmdAH-24.20.2 {Tcl_FileObjCmd: mtime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit} -setup {
    set filename [makeFile "" foo.text]
} -body {
    list [file mtime $filename 3155760000] [file mtime $filename]
} -cleanup {
    file delete -force $filename
} -result {3155760000 3155760000}

# owned

test cmdAH-25.1 {Tcl_FileObjCmd: owned} {
    list [catch {file owned a b} msg] $msg
} {1 {wrong # args: should be "file owned name"}}
test cmdAH-25.2 {Tcl_FileObjCmd: owned} -constraints win -setup {
    set fn $gorpfile
    # prefer temp file to check owner (try to avoid bug [7de2d722bd]):
    if {
	[info exists ::env(TEMP)] && [file isdirectory $::env(TEMP)] &&
        [file dirname $fn] ne [file normalize $::env(TEMP)]
    } {
	set fn [file join $::env(TEMP)/test-owner-from-tcl.txt]
	set fn [makeFile "data" test-owner-from-tcl.txt $::env(TEMP)]
    }
    # be sure we have really owned this file before trying to check that
    # (avoid dependency on admin with UAC and the setting "System objects:
    # Default owner for objects created by members of the Administrators group"):
    catch {
	exec takeown /F [file nativename $fn]
    }
} -body {
    file owned $fn
} -cleanup {
    if {$fn ne $gorpfile} {
	removeFile $fn
    }
} -result 1
test cmdAH-25.2.1 {Tcl_FileObjCmd: owned} -constraints unix -setup {
    # Avoid problems with AFS
    set tmpfile [makeFile "data" touch.me /tmp]
} -body {
    file owned $tmpfile
} -cleanup {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<







1267
1268
1269
1270
1271
1272
1273
















1274
1275
1276
1277
1278
1279
















1280




1281
1282
1283
1284
1285
1286
1287
    file mtime $dirname 0
    set new [file mtime $dirname]
    list $new [expr {$old != $new}]
} -cleanup {
    file delete -force $dirname
} -result {0 1}

















# owned

test cmdAH-25.1 {Tcl_FileObjCmd: owned} {
    list [catch {file owned a b} msg] $msg
} {1 {wrong # args: should be "file owned name"}}
test cmdAH-25.2 {Tcl_FileObjCmd: owned} -constraints win -body {
















    file owned $gorpfile




} -result 1
test cmdAH-25.2.1 {Tcl_FileObjCmd: owned} -constraints unix -setup {
    # Avoid problems with AFS
    set tmpfile [makeFile "data" touch.me /tmp]
} -body {
    file owned $tmpfile
} -cleanup {

Changes to tests/cmdIL.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
source [file join [file dirname [info script]] internals.tcl]
namespace import -force ::tcltest::internals::*

test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort -foo {1 3 2 5}} msg] $msg
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}







<
<







11
12
13
14
15
16
17


18
19
20
21
22
23
24
if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]



test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort -foo {1 3 2 5}} msg] $msg
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
	lindex [lsort -real -index $l $n] 1 1
    }
    expr srand(1)
    test_lsort 0
} -result 0 -cleanup {
    rename test_lsort ""
}
test cmdIL-5.7 {lsort memory exhaustion} -constraints {testWithLimit} -body {
    # test it in child process (with limited address space) ca. 80MB extra memory
    # on x64 system it would be not enough to sort 4M items (the half 2M only),
    # warn and skip if no error (enough memory) or error by list creation:
    testWithLimit \
	-warn-on-code 0 -warn-on-alloc-error 1 \
	-addmem [expr {$tcl_platform(pointerSize)*4000000 + $tcl_platform(pointerSize)*3*2000000}] \
    {
	# create list and get length (avoid too long output in interactive shells):
	llength [set l [lrepeat 4000000 ""]]
	# test OOM:
	llength [lsort $l]
    }
    # expecting error no memory by sort
} -returnCodes 1 -result {no enough memory to proccess sort of 4000000 items}

# Compiled version
test cmdIL-6.1 {lassign command syntax} -body {
    proc testLassign {} {
	lassign
    }
    testLassign







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







441
442
443
444
445
446
447















448
449
450
451
452
453
454
	lindex [lsort -real -index $l $n] 1 1
    }
    expr srand(1)
    test_lsort 0
} -result 0 -cleanup {
    rename test_lsort ""
}
















# Compiled version
test cmdIL-6.1 {lassign command syntax} -body {
    proc testLassign {} {
	lassign
    }
    testLassign

Changes to tests/cmdMZ.test.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

namespace eval ::tcl::test::cmdMZ {
    namespace import ::tcltest::cleanupTests
    namespace import ::tcltest::customMatch
    namespace import ::tcltest::makeFile
    namespace import ::tcltest::removeFile
    namespace import ::tcltest::temporaryDirectory
    namespace import ::tcltest::testConstraint
    namespace import ::tcltest::test

    if {[namespace which -command ::tcl::unsupported::timerate] ne ""} {
	namespace import ::tcl::unsupported::timerate
    }

# Tcl_PwdObjCmd

test cmdMZ-1.1 {Tcl_PwdObjCmd} {
    list [catch {pwd a} msg] $msg
} {1 {wrong # args: should be "pwd"}}
test cmdMZ-1.2 {Tcl_PwdObjCmd: simple pwd} {
    catch pwd







<


<
<
<
<







18
19
20
21
22
23
24

25
26




27
28
29
30
31
32
33

namespace eval ::tcl::test::cmdMZ {
    namespace import ::tcltest::cleanupTests
    namespace import ::tcltest::customMatch
    namespace import ::tcltest::makeFile
    namespace import ::tcltest::removeFile
    namespace import ::tcltest::temporaryDirectory

    namespace import ::tcltest::test





# Tcl_PwdObjCmd

test cmdMZ-1.1 {Tcl_PwdObjCmd} {
    list [catch {pwd a} msg] $msg
} {1 {wrong # args: should be "pwd"}}
test cmdMZ-1.2 {Tcl_PwdObjCmd: simple pwd} {
    catch pwd
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
            return -code error -errorcode {a b} c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}

test cmdMZ-return-2.16 {return opton handling} -setup {
        proc p {} {
            return -code error -errorcode [list a b] c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}

test cmdMZ-return-2.17 {return opton handling} -setup {
        proc p {} {
            return -code error -errorcode a\ b c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}


# Check that the result of a [return -options $opts $result] is
# indistinguishable from that of the originally caught script, no
# matter what the script is/does.  (TIP 90)
set i 0
foreach script {
	{}







|









|









|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
            return -code error -errorcode {a b} c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}
   
test cmdMZ-return-2.16 {return opton handling} -setup {
        proc p {} {
            return -code error -errorcode [list a b] c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}
   
test cmdMZ-return-2.17 {return opton handling} -setup {
        proc p {} {
            return -code error -errorcode a\ b c
        }
    } -body {
        list [catch p result] $result $::errorCode
    } -cleanup {
        rename p {}
    } -result {1 c {a b}}
   

# Check that the result of a [return -options $opts $result] is
# indistinguishable from that of the originally caught script, no
# matter what the script is/does.  (TIP 90)
set i 0
foreach script {
	{}
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

# The tests for Tcl_ScanObjCmd are in scan.test

# Tcl_SourceObjCmd
# More tests of Tcl_SourceObjCmd are in source.test

test cmdMZ-3.3 {Tcl_SourceObjCmd: error conditions} -constraints {
    unixOrWin
} -body {
    list [catch {source} msg] $msg
} -match glob -result {1 {wrong # args: should be "source*fileName"}}
test cmdMZ-3.4 {Tcl_SourceObjCmd: error conditions} -constraints {
    unixOrWin
} -body {
    list [catch {source a b} msg] $msg
} -match glob -result {1 {wrong # args: should be "source*fileName"}}

proc ListGlobMatch {expected actual} {
    if {[llength $expected] != [llength $actual]} {
        return 0







|




|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

# The tests for Tcl_ScanObjCmd are in scan.test

# Tcl_SourceObjCmd
# More tests of Tcl_SourceObjCmd are in source.test

test cmdMZ-3.3 {Tcl_SourceObjCmd: error conditions} -constraints {
    unixOrPc
} -body {
    list [catch {source} msg] $msg
} -match glob -result {1 {wrong # args: should be "source*fileName"}}
test cmdMZ-3.4 {Tcl_SourceObjCmd: error conditions} -constraints {
    unixOrPc
} -body {
    list [catch {source a b} msg] $msg
} -match glob -result {1 {wrong # args: should be "source*fileName"}}

proc ListGlobMatch {expected actual} {
    if {[llength $expected] != [llength $actual]} {
        return 0
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
} {{} {} {} {}}
test cmdMZ-4.10 {Tcl_SplitObjCmd: basic split commands} {
    proc foo {} {
        set x {}
        foreach f [split {]\n} {}] {
            append x $f
        }
        return $x
    }
    foo
} {]\n}
test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} {
    proc foo {} {
        set x ab\000c
        set y [split $x {}]







|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
} {{} {} {} {}}
test cmdMZ-4.10 {Tcl_SplitObjCmd: basic split commands} {
    proc foo {} {
        set x {}
        foreach f [split {]\n} {}] {
            append x $f
        }
        return $x	
    }
    foo
} {]\n}
test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} {
    proc foo {} {
        set x ab\000c
        set y [split $x {}]
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
    split "a\u4e4eb qw\u5e4e\x4e wq" " \u4e4e"
} "a b qw\u5e4eN wq"

# The tests for Tcl_StringObjCmd are in string.test
# The tests for Tcl_SubstObjCmd are in subst.test
# The tests for Tcl_SwitchObjCmd are in switch.test

# todo: rewrite this if monotonic clock is provided resp. command "after"
# gets microsecond accuracy (RFE [fdfbd5e10] gets merged):
proc _nrt_sleep {msec} {
    set usec [expr {$msec * 1000}]
    set stime [clock microseconds]
    while {abs([clock microseconds] - $stime) < $usec} {
      # don't use after 0 unless it's NRT-capable, so yes - busy-wait (but it's more precise):
      # after 0
    }
}
_nrt_sleep 0; # warm up (clock, compile, etc)

test cmdMZ-5.1 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time} msg] $msg
} {1 {wrong # args: should be "time command ?count?"}}
test cmdMZ-5.2 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time a b c} msg] $msg
} {1 {wrong # args: should be "time command ?count?"}}
test cmdMZ-5.3 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time a b} msg] $msg
} {1 {expected integer but got "b"}}
test cmdMZ-5.4 {Tcl_TimeObjCmd: nothing happens with negative iteration counts} {
    time bogusCmd -12456
} {0 microseconds per iteration}
test cmdMZ-5.5 {Tcl_TimeObjCmd: result format} {
    regexp {^\d+ microseconds per iteration} [time {format 1}]
} 1
test cmdMZ-5.6 {Tcl_TimeObjCmd: slower commands take longer} -body {
    set m1 [lindex [time {_nrt_sleep 0.01}] 0]
    set m2 [lindex [time {_nrt_sleep 10.0}] 0]
    list \
	[expr {$m1 < $m2}] \
	$m1 $m2; # interesting only in error case.
} -match glob -result [list 1 *]
test cmdMZ-5.7 {Tcl_TimeObjCmd: errors generate right trace} {
    list [catch {time {error foo}} msg] $msg $::errorInfo
} {1 foo {foo
    while executing
"error foo"
    invoked from within
"time {error foo}"}}
test cmdMZ-5.7.1 {Tcl_TimeObjCmd: return from time} {
    set x 0
    proc r1 {} {upvar x x; time {incr x; return "r1"; incr x} 10}
    list [r1] $x
} {r1 1}
test cmdMZ-5.8 {Tcl_TimeObjCmd: done optimization: nested call of self inside time (if compiled)} {
    set x [set y 0]
    set m1 {
	if {[incr x] <= 5} {
	    # nested call should return result, so covering that:
	    if {![string is integer -strict [eval $m1]]} {error unexpected}
	}
	# increase again (no "continue" from nested call):
	incr x
    }
    time {incr y; eval $m1} 5
    list $y $x
} {5 20}

test cmdMZ-6.1 {Tcl_TimeRateObjCmd: basic format of command} {
    list [catch {timerate} msg] $msg
} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time ?max-count??"}}
test cmdMZ-6.2.1 {Tcl_TimeRateObjCmd: basic format of command} {
    list [catch {timerate a b c d} msg] $msg
} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time ?max-count??"}}
test cmdMZ-6.2.2 {Tcl_TimeRateObjCmd: basic format of command} {
    list [catch {timerate a b c} msg] $msg
} {1 {expected integer but got "b"}}
test cmdMZ-6.2.3 {Tcl_TimeRateObjCmd: basic format of command} {
    list [catch {timerate a b} msg] $msg
} {1 {expected integer but got "b"}}
test cmdMZ-6.3 {Tcl_TimeRateObjCmd: basic format of command} {
    list [catch {timerate -overhead b {} a b} msg] $msg
} {1 {expected floating-point number but got "b"}}
test cmdMZ-6.4 {Tcl_TimeRateObjCmd: compile of script happens even with negative iteration counts} {
    list [catch {timerate "foreach a {c d e} \{" -12456} msg] $msg
} {1 {missing close-brace}}
test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
    regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0]
} 1
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
    regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1
test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measument} -body {
    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \
	[expr {[lindex $m1 0] < 100}] \
	[expr {[lindex $m2 0] > 100}] \
	[expr {[lindex $m1 2] > 500}] \
	[expr {[lindex $m2 2] < 500}] \
	[expr {[lindex $m1 4] > 10000}] \
	[expr {[lindex $m2 4] < 10000}] \
	[expr {[lindex $m1 6] > 5 && [lindex $m1 6] < 100}] \
	[expr {[lindex $m2 6] > 5 && [lindex $m2 6] < 100}] \
    ] $m1 $m2; # interesting only in error case.
} -match glob -result [list [lrepeat 9 1] *]
test cmdMZ-6.7 {Tcl_TimeRateObjCmd: errors generate right trace} {
    list [catch {timerate {error foo} 1} msg] $msg $::errorInfo
} {1 foo {foo
    while executing
"error foo"
    invoked from within
"timerate {error foo} 1"}}
test cmdMZ-6.7.1 {Tcl_TimeRateObjCmd: return from timerate} {
    set x 0
    proc r1 {} {upvar x x; timerate {incr x; return "r1"; incr x} 1000 10}
    list [r1] $x
} {r1 1}
test cmdMZ-6.8 {Tcl_TimeRateObjCmd: allow (conditional) break from timerate} -body {
    set m1 [timerate {break}]
    list [list \
	[expr {[lindex $m1 0] < 1000}] \
	[expr {[lindex $m1 2] == 1}] \
	[expr {[lindex $m1 4] > 1000}] \
	[expr {[lindex $m1 6] < 10}] \
    ] $m1; # interesting only in error case.
} -match glob -result [list {1 1 1 1} *]
test cmdMZ-6.8.1 {Tcl_TimeRateObjCmd: allow (conditional) continue in timerate} -body {
    set m1 [timerate {continue; return -code error "unexpected"} 1000 10]
    list [list \
	[expr {[lindex $m1 0] < 1000}] \
	[expr {[lindex $m1 2] == 10}] \
	[expr {[lindex $m1 4] > 1000}] \
	[expr {[lindex $m1 6] < 100}] \
    ] $m1; # interesting only in error case.
} -match glob -result [list {1 1 1 1} *]
test cmdMZ-6.9 {Tcl_TimeRateObjCmd: max count of iterations} {
    set m1 [timerate {} 1000 5];	# max-count wins
    set m2 [timerate {_nrt_sleep 20} 1 5];	# max-time wins
    list [lindex $m1 2] [lindex $m2 2]
} {5 1}
test cmdMZ-6.10 {Tcl_TimeRateObjCmd: huge overhead cause 0us result} -body {
    set m1 [timerate -overhead 1e6 {_nrt_sleep 10} 100 1]
    list [list \
	[expr {[lindex $m1 0] == 0.0}] \
	[expr {[lindex $m1 2] == 1}] \
	[expr {[lindex $m1 4] == 1000000}] \
	[expr {[lindex $m1 6] <= 0.001}] \
    ] $m1; # interesting only in error case.
} -match glob -result [list {1 1 1 1} *]
test cmdMZ-6.11 {Tcl_TimeRateObjCmd: done/continue optimization rollback} {
    set m1 {set m2 ok}
    if 1 $m1
    timerate $m1 1000 10
    if 1 $m1; # if rollback is missing throws an error: invoked "continue" outside of a loop
} ok
test cmdMZ-6.12 {Tcl_TimeRateObjCmd: done optimization: nested call of self inside timerate} {
    set x 0
    set m1 {
	if {[incr x] <= 5} {
	    # nested call should return result, so covering that:
	    if {![string is integer -strict [eval $m1]]} {error unexpected}
	}
	# increase again (no "continue" from nested call):
	incr x
    }
    list [lindex [timerate $m1 1000 5] 2] $x
} {5 20}

# The tests for Tcl_WhileObjCmd are in while.test

# cleanup
cleanupTests
}
namespace delete ::tcl::test::cmdMZ
return







<
<
<
<
<
<
<
<
<
<
<
<















|
|
<
|
<
<
<







<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







317
318
319
320
321
322
323












324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

341



342
343
344
345
346
347
348











349













































































































350
351
352
353
354
355
356
    split "a\u4e4eb qw\u5e4e\x4e wq" " \u4e4e"
} "a b qw\u5e4eN wq"

# The tests for Tcl_StringObjCmd are in string.test
# The tests for Tcl_SubstObjCmd are in subst.test
# The tests for Tcl_SwitchObjCmd are in switch.test













test cmdMZ-5.1 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time} msg] $msg
} {1 {wrong # args: should be "time command ?count?"}}
test cmdMZ-5.2 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time a b c} msg] $msg
} {1 {wrong # args: should be "time command ?count?"}}
test cmdMZ-5.3 {Tcl_TimeObjCmd: basic format of command} {
    list [catch {time a b} msg] $msg
} {1 {expected integer but got "b"}}
test cmdMZ-5.4 {Tcl_TimeObjCmd: nothing happens with negative iteration counts} {
    time bogusCmd -12456
} {0 microseconds per iteration}
test cmdMZ-5.5 {Tcl_TimeObjCmd: result format} {
    regexp {^\d+ microseconds per iteration} [time {format 1}]
} 1
test cmdMZ-5.6 {Tcl_TimeObjCmd: slower commands take longer} {
    expr {[lindex [time {after 2}] 0] < [lindex [time {after 1000}] 0]}

} 1



test cmdMZ-5.7 {Tcl_TimeObjCmd: errors generate right trace} {
    list [catch {time {error foo}} msg] $msg $::errorInfo
} {1 foo {foo
    while executing
"error foo"
    invoked from within
"time {error foo}"}}

























































































































# The tests for Tcl_WhileObjCmd are in while.test

# cleanup
cleanupTests
}
namespace delete ::tcl::test::cmdMZ
return

Changes to tests/compile.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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# This file contains tests for the files tclCompile.c, tclCompCmds.c and
# tclLiteral.c
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import -force ::tcltest::*

testConstraint exec       [llength [info commands exec]]
testConstraint memory     [llength [info commands memory]]
testConstraint testevalex [llength [info commands testevalex]]

# The following tests are very incomplete, although the rest of the
# test suite covers this file fairly well.

catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}

test compile-1.1 {TclCompileString: look up cmds in proc ns, not current ns} -setup {
    catch {namespace delete test_ns_compile}
    catch {unset x}
} -body {
    set x 123
    namespace eval test_ns_compile {
        proc set {args} {
            global x
            lappend x test_ns_compile::set
        }
        proc p {} {
            set 0
        }
    }
    list [test_ns_compile::p] [set x]
} -result {{123 test_ns_compile::set} {123 test_ns_compile::set}}
test compile-1.2 {TclCompileString, error result is reset if TclGetLong determines word isn't an integer} {
    proc p {x} {info commands 3m}
    list [catch {p} msg] $msg
} {1 {wrong # args: should be "p x"}}

test compile-2.1 {TclCompileDollarVar: global scalar name with ::s} -setup {
    catch {unset x}
} -body {
    set x 123
    list $::x [expr {[lsearch -exact [info globals] x] != 0}]
} -result {123 1}
test compile-2.2 {TclCompileDollarVar: global scalar name with ::s} -setup {
    catch {unset y}
} -body {
    proc p {} {
        set ::y 789
        return $::y
    }
    list [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
} -result {789 789 1}
test compile-2.3 {TclCompileDollarVar: global array name with ::s} -setup {
    catch {unset a}
} -body {
    set ::a(1) 2
    list $::a(1) [set ::a($::a(1)) 3] $::a(2) [expr {[lsearch -exact [info globals] a] != 0}]
} -result {2 3 3 1}
test compile-2.4 {TclCompileDollarVar: global scalar name with ::s} {
    catch {unset a}
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
    }
    list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} {1 1 1}
test compile-2.5 {TclCompileDollarVar: global array, called as ${arrName(0)}} {
    catch {unset a}
    proc p {} {
	global a
        set a(1) 1
        return ${a(1)}$::a(1)$a(1)
    }
    list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} {111 1 1}

test compile-3.1 {TclCompileCatchCmd: only catch cmds with scalar vars are compiled inline} -setup {
    catch {unset a}
} -body {
    set a(1) xyzzyx
    proc p {} {
        global a
        catch {set x 123} a(1)
    }
    list [p] $a(1)
} -result {0 123}
test compile-3.2 {TclCompileCatchCmd: non-local variables} {
    set ::foo 1
    proc catch-test {} {
	catch {set x 3} ::foo
    }
    catch-test
    set ::foo
} 3
test compile-3.3 {TclCompileCatchCmd: overagressive compiling [bug 219184]} {
    proc catch-test {str} {
	catch [eval $str GOOD]
	error BAD
    }
    catch {catch-test error} ::foo
    set ::foo
} {GOOD}
test compile-3.4 {TclCompileCatchCmd: bcc'ed [return] is caught} {
    proc foo {} {
	set fail [catch {
	    return 1
	}] ; # {}
	return 2
    }
    foo
} {2}
test compile-3.5 {TclCompileCatchCmd: recover from error, [Bug 705406]} {
    proc foo {} {
	catch {
	    if {[a]} {
		if b {}
	    }
	}
    }
    list [catch foo msg] $msg
} {0 1}
test compile-3.6 {TclCompileCatchCmd: error in storing result [Bug 3098302]} {*}{
     -setup {
	 namespace eval catchtest {
	     variable result1 {}
|
|

|
|
|




|
|
















|
|


<











|




<
|

<


|
|

<





|
|

<


|


















|

<






|




















|









|
|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
# This file contains tests for the files tclCompile.c, tclCompCmds.c
# and tclLiteral.c
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import -force ::tcltest::*

testConstraint exec       [llength [info commands exec]]
testConstraint memory     [llength [info commands memory]]
testConstraint testevalex [llength [info commands testevalex]]

# The following tests are very incomplete, although the rest of the
# test suite covers this file fairly well.

catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}

test compile-1.1 {TclCompileString: look up cmds in proc ns, not current ns} {
    catch {namespace delete test_ns_compile}
    catch {unset x}

    set x 123
    namespace eval test_ns_compile {
        proc set {args} {
            global x
            lappend x test_ns_compile::set
        }
        proc p {} {
            set 0
        }
    }
    list [test_ns_compile::p] [set x]
} {{123 test_ns_compile::set} {123 test_ns_compile::set}}
test compile-1.2 {TclCompileString, error result is reset if TclGetLong determines word isn't an integer} {
    proc p {x} {info commands 3m}
    list [catch {p} msg] $msg
} {1 {wrong # args: should be "p x"}}

test compile-2.1 {TclCompileDollarVar: global scalar name with ::s} {
    catch {unset x}

    set x 123
    list $::x [expr {[lsearch -exact [info globals] x] != 0}]
} {123 1}
test compile-2.2 {TclCompileDollarVar: global scalar name with ::s} {
    catch {unset y}

    proc p {} {
        set ::y 789
        return $::y
    }
    list [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
} {789 789 1}
test compile-2.3 {TclCompileDollarVar: global array name with ::s} {
    catch {unset a}

    set ::a(1) 2
    list $::a(1) [set ::a($::a(1)) 3] $::a(2) [expr {[lsearch -exact [info globals] a] != 0}]
} {2 3 3 1}
test compile-2.4 {TclCompileDollarVar: global scalar name with ::s} {
    catch {unset a}
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
    }
    list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} {1 1 1}
test compile-2.5 {TclCompileDollarVar: global array, called as ${arrName(0)}} {
    catch {unset a}
    proc p {} {
	global a
        set a(1) 1
        return ${a(1)}$::a(1)$a(1)
    }
    list [p] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} {111 1 1}

test compile-3.1 {TclCompileCatchCmd: only catch cmds with scalar vars are compiled inline} {
    catch {unset a}

    set a(1) xyzzyx
    proc p {} {
        global a
        catch {set x 123} a(1)
    }
    list [p] $a(1)
} {0 123}
test compile-3.2 {TclCompileCatchCmd: non-local variables} {
    set ::foo 1
    proc catch-test {} {
	catch {set x 3} ::foo
    }
    catch-test
    set ::foo
} 3
test compile-3.3 {TclCompileCatchCmd: overagressive compiling [bug 219184]} {
    proc catch-test {str} {
	catch [eval $str GOOD]
	error BAD
    }
    catch {catch-test error} ::foo
    set ::foo
} {GOOD}
test compile-3.4 {TclCompileCatchCmd: bcc'ed [return] is caught} {
    proc foo {} {
	set fail [catch {
	    return 1
	}] ; # {}	
	return 2
    }
    foo
} {2}
test compile-3.5 {TclCompileCatchCmd: recover from error, [Bug 705406]} {
    proc foo {} {
	catch {
	    if {[a]} {
		if b {}
	    }   
	}   
    }
    list [catch foo msg] $msg
} {0 1}
test compile-3.6 {TclCompileCatchCmd: error in storing result [Bug 3098302]} {*}{
     -setup {
	 namespace eval catchtest {
	     variable result1 {}
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    proc foreach-test {} {
	foreach ::foo {1 2 3} {}
    }
    foreach-test
    set ::foo
} 3

test compile-6.1 {TclCompileSetCmd: global scalar names with ::s} -setup {
    catch {unset x}
    catch {unset y}
} -body {
    set x 123
    proc p {} {
        set ::y 789
        return $::y
    }
    list $::x [expr {[lsearch -exact [info globals] x] != 0}] \
         [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
} -result {123 1 789 789 1}
test compile-6.2 {TclCompileSetCmd: global array names with ::s} -setup {
    catch {unset a}
} -body {
    set ::a(1) 2
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
    }
    list $::a(1) [p] [set ::a($::a(1)) 3] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} -result {2 1 3 3 1}
test compile-6.3 {TclCompileSetCmd: namespace var names with ::s} -setup {
    catch {namespace delete test_ns_compile}
    catch {unset x}
} -body {
    namespace eval test_ns_compile {
        variable v hello
        variable arr
        set ::x $::test_ns_compile::v
	set ::test_ns_compile::arr(1) 123
    }
    list $::x $::test_ns_compile::arr(1)
} -result {hello 123}

test compile-7.1 {TclCompileWhileCmd: command substituted test expression} {
    set i 0
    set j 0
    # Should be "forever"
    while [expr $i < 3] {
	set j [incr i]







|


<







|
|

<






|
|


<







|







181
182
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    proc foreach-test {} {
	foreach ::foo {1 2 3} {}
    }
    foreach-test
    set ::foo
} 3

test compile-6.1 {TclCompileSetCmd: global scalar names with ::s} {
    catch {unset x}
    catch {unset y}

    set x 123
    proc p {} {
        set ::y 789
        return $::y
    }
    list $::x [expr {[lsearch -exact [info globals] x] != 0}] \
         [p] $::y [expr {[lsearch -exact [info globals] y] != 0}]
} {123 1 789 789 1}
test compile-6.2 {TclCompileSetCmd: global array names with ::s} {
    catch {unset a}

    set ::a(1) 2
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
    }
    list $::a(1) [p] [set ::a($::a(1)) 3] $::a(1) [expr {[lsearch -exact [info globals] a] != 0}]
} {2 1 3 3 1}
test compile-6.3 {TclCompileSetCmd: namespace var names with ::s} {
    catch {namespace delete test_ns_compile}
    catch {unset x}

    namespace eval test_ns_compile {
        variable v hello
        variable arr
        set ::x $::test_ns_compile::v
	set ::test_ns_compile::arr(1) 123
    }
    list $::x $::test_ns_compile::arr(1)
} {hello 123}

test compile-7.1 {TclCompileWhileCmd: command substituted test expression} {
    set i 0
    set j 0
    # Should be "forever"
    while [expr $i < 3] {
	set j [incr i]
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
    p
} -returnCodes error -match glob -result *
test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; llength "\{" }
    list [catch {p} msg] $msg
} {1 {unmatched open brace in list}}

#
# Special section for tests of tclLiteral.c
# The following tests check for incorrect memory handling in
# TclReleaseLiteral. They are only effective when tcl is compiled with
# TCL_MEM_DEBUG
#
# Special test for leak on interp delete [Bug 467523].
test compile-12.1 {testing literal leak on interp delete} -setup {
    proc getbytes {} {
	set lines [split [memory info] "\n"]
	lindex $lines 3 3
    }
} -constraints memory -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	interp create foo
	foo eval {
	    namespace eval bar {}
	}
	interp delete foo
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    rename getbytes {}
    unset -nocomplain end i tmp leakedBytes
} -result 0
# Special test for a memory error in a preliminary fix of [Bug 467523].  It
# requires executing a helpfile.  Presumably the child process is used because
# when this test fails, it crashes.
test compile-12.2 {testing error on literal deletion} -constraints {memory exec} -body {
    set sourceFile [makeFile {
	for {set i 0} {$i < 5} {incr i} {
	    namespace eval bar {}
	    namespace delete bar
	}
	puts 0
    } source.file]
    exec [interpreter] $sourceFile
} -cleanup {
    catch {removeFile $sourceFile}
} -result 0
# Test to catch buffer overrun in TclCompileTokens from buf 530320
test compile-12.3 {check for a buffer overrun} -body {
    proc crash {} {
	puts $array([expr {a+2}])
    }
    crash
} -returnCodes error -cleanup {
    rename crash {}
} -match glob -result *
test compile-12.4 {TclCleanupLiteralTable segfault} -body {
    # Tcl Bug 1001997
    # Here, we're trying to test a case that causes a crash in
    # TclCleanupLiteralTable.  The conditions that we're trying to establish
    # are:
    # - TclCleanupLiteralTable is attempting to clean up a bytecode object in
    #   the literal table.
    # - The bytecode object in question contains the only reference to another
    #   literal.
    # - The literal in question is in the same hash bucket as the bytecode
    #   object, and immediately follows it in the chain.
    # Since newly registered literals are added at the FRONT of the bucket
    # chains, and since the bytecode object is registered before its literals,
    # this is difficult to achieve.  What we do is:
    #  (a) do a [namespace eval] of a string that's calculated to hash into
    #      the same bucket as a literal that it contains.  In this case, the

    #      script and the variable 'bugbug' land in the same bucket.
    #  (b) do a [namespace eval] of a string that contains enough literals to
    #      force TclRegisterLiteral to rebuild the global literal table.  The
    #      newly created hash buckets will contain the literals, IN REVERSE
    #      ORDER, thus putting the bytecode immediately ahead of 'bugbug' and

    #      'bug4345bug'.  The bytecode object will contain the only references
    #      to those two literals.
    #  (c) Delete the interpreter to invoke TclCleanupLiteralTable and tickle
    #      the bug.
    proc foo {} {
	set i [interp create]
	$i eval {
	    namespace eval ::w {concat 4649; variable bugbug}
	    namespace eval ::w {
		concat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 \
		    x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 \







|


|
|










|
|

|









|
|
|








|















|
|
|
|
|
|


|
|
|
|
|
>
|
|
|
|
|
>
|
<
|
|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
    p
} -returnCodes error -match glob -result *
test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; llength "\{" }
    list [catch {p} msg] $msg
} {1 {unmatched open brace in list}}

# 
# Special section for tests of tclLiteral.c
# The following tests check for incorrect memory handling in
# TclReleaseLiteral. They are only effective when tcl is compiled 
# with TCL_MEM_DEBUG
#
# Special test for leak on interp delete [Bug 467523].
test compile-12.1 {testing literal leak on interp delete} -setup {
    proc getbytes {} {
	set lines [split [memory info] "\n"]
	lindex $lines 3 3
    }
} -constraints memory -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	interp create foo 
	foo eval { 
	    namespace eval bar {}
	} 
	interp delete foo
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    rename getbytes {}
    unset -nocomplain end i tmp leakedBytes
} -result 0
# Special test for a memory error in a preliminary fix of [Bug 467523]. 
# It requires executing a helpfile.  Presumably the child process is
# used because when this test fails, it crashes.
test compile-12.2 {testing error on literal deletion} -constraints {memory exec} -body {
    set sourceFile [makeFile {
	for {set i 0} {$i < 5} {incr i} {
	    namespace eval bar {}
	    namespace delete bar
	}
	puts 0
    } source.file]
    exec [interpreter] $sourceFile 
} -cleanup {
    catch {removeFile $sourceFile}
} -result 0
# Test to catch buffer overrun in TclCompileTokens from buf 530320
test compile-12.3 {check for a buffer overrun} -body {
    proc crash {} {
	puts $array([expr {a+2}])
    }
    crash
} -returnCodes error -cleanup {
    rename crash {}
} -match glob -result *
test compile-12.4 {TclCleanupLiteralTable segfault} -body {
    # Tcl Bug 1001997
    # Here, we're trying to test a case that causes a crash in
    # TclCleanupLiteralTable.  The conditions that we're trying to
    # establish are:
    # - TclCleanupLiteralTable is attempting to clean up a bytecode
    #   object in the literal table.
    # - The bytecode object in question contains the only reference
    #   to another literal.
    # - The literal in question is in the same hash bucket as the bytecode
    #   object, and immediately follows it in the chain.
    # Since newly registered literals are added at the FRONT of the
    # bucket chains, and since the bytecode object is registered before
    # its literals, this is difficult to achieve.  What we do is:
    #  (a) do a [namespace eval] of a string that's calculated to
    #      hash into the same bucket as a literal that it contains.
    #      In this case, the script and the variable 'bugbug' 
    #      land in the same bucket.
    #  (b) do a [namespace eval] of a string that contains enough
    #      literals to force TclRegisterLiteral to rebuild the global
    #      literal table.  The newly created hash buckets will contain
    #      the literals, IN REVERSE ORDER, thus putting the bytecode
    #      immediately ahead of 'bugbug' and 'bug4345bug'.  The bytecode
    #      object will contain the only references to those two literals.

    #  (c) Delete the interpreter to invoke TclCleanupLiteralTable
    #      and tickle the bug.
    proc foo {} {
	set i [interp create]
	$i eval {
	    namespace eval ::w {concat 4649; variable bugbug}
	    namespace eval ::w {
		concat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 \
		    x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 \
413
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
	return ok
    }
    foo
} -cleanup {
    rename foo {}
} -result ok

# Special test for underestimating the maxStackSize required for a compiled
# command. A failure will cause a segfault in the child process.

test compile-13.1 {testing underestimate of maxStackSize in list cmd} {exec} {
    set body {set x [list}
    for {set i 0} {$i < 3000} {incr i} {
	append body " $i"
    }
    append body {]; puts OK}
    regsub BODY {proc crash {} {BODY}; crash} $body script
    list [catch {exec [interpreter] << $script} msg] $msg
} {0 OK}

# Tests of nested compile (body in body compilation), should not generate stack overflow
# (with abnormal program termination), bug [fec0c17d39]:
proc _ti_gencode {} {
    # creates test interpreter on demand with [gencode] generator:
    if {[interp exists ti]} {
	return
    }
    interp create ti
    ti eval {proc gencode {nr {cmd eval} {nl 0}} {
	set code ""
	set e ""; if {$nl} {set e "\n"}
	for {set i 0} {$i < $nr} {incr i} {
	    append code "$cmd \{$e"
	}
	append code "lappend result 1$e"
	for {set i 0} {$i < $nr} {incr i} {
	    append code "\}$e"
	}
	#puts [format "%% %.40s ... %d bytes" $code [string length $code]]
	return $code
    }}
}
test compile-13.2 {TclCompileScript: testing expected nested scripts compilation} -setup {
    _ti_gencode
    interp recursionlimit ti [expr {10000+50}]
    ti eval {set result {}}
} -body {
    # Test different compilation variants (instructions evalStk, invokeStk, etc),
    # with 1500 (1000 in debug) nested scripts (bodies). If you get SO/SF exceptions on some low-stack
    # boxes or systems, please don't decrease it (either provide a constraint)
    ti eval {foreach cmd {eval "if 1" catch} {
	set c [gencode [expr {![::tcl::pkgconfig get debug] ? 1500 : 1000}] $cmd]
	if 1 $c
    }}
    ti eval {set result}
} -result {1 1 1}
test compile-13.3 {TclCompileScript: testing check of max depth by nested scripts compilation} -setup {
    _ti_gencode
    interp recursionlimit ti 100
    ti eval {set result {}}
} -body {
    # Test different compilation variants (instructions evalStk, invokeStk, etc),
    # with 500 nested scripts (bodies). It must generate "too many nested compilations"
    # error for any variant we're testing here:
    ti eval {foreach cmd {eval "if 1" catch} {
	set c [gencode 500 $cmd]
	lappend errors [catch $c e] $e
    }}
    #puts $errors
    # all of nested calls exceed the limit, so must end with "too many nested compilations"
    # (or evaluations, depending on compile method/instruction and "mixed" compile within
    # evaliation), so no one succeeds, the result must be empty:
    ti eval {set result}
} -result {}
#
# clean up:
if {[interp exists ti]} {
    interp delete ti
}
rename _ti_gencode {}

# Tests compile-14.* for [Bug 599788] [Bug 0c043a175a47da8c2342]
test compile-14.1 {testing errors in element name; segfault?} {} {
     catch {set a([error])} msg1
     catch {set bubba([join $abba $jubba]) $vol} msg2
     list $msg1 $msg2
} {{wrong # args: should be "error message ?errorInfo? ?errorCode?"} {can't read "abba": no such variable}}

test compile-14.2 {testing element name "$"} -body {
    unset -nocomplain a
    set a() 1
    set a(1) 2
    set a($) 3
    list [set a()] [set a(1)] [set a($)] [unset a() a(1); lindex [array names a] 0]
} -cleanup {unset a} -result [list 1 2 3 {$}]


# Tests compile-15.* cover Tcl Bug 633204
test compile-15.1 {proper TCL_RETURN code from [return]} {







|
|
>










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424





























































425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
	return ok
    }
    foo
} -cleanup {
    rename foo {}
} -result ok

# Special test for underestimating the maxStackSize required for a
# compiled command. A failure will cause a segfault in the child 
# process.
test compile-13.1 {testing underestimate of maxStackSize in list cmd} {exec} {
    set body {set x [list}
    for {set i 0} {$i < 3000} {incr i} {
	append body " $i"
    }
    append body {]; puts OK}
    regsub BODY {proc crash {} {BODY}; crash} $body script
    list [catch {exec [interpreter] << $script} msg] $msg
} {0 OK}






























































# Tests compile-14.* for [Bug 599788] [Bug 0c043a175a47da8c2342]
test compile-14.1 {testing errors in element name; segfault?} {} {
     catch {set a([error])} msg1
     catch {set bubba([join $abba $jubba]) $vol} msg2
     list $msg1 $msg2
} {{wrong # args: should be "error message ?errorInfo? ?errorCode?"} {can't read "abba": no such variable}}

test compile-14.2 {testing element name "$"} -body {
    unset -nocomplain a
    set a() 1
    set a(1) 2 
    set a($) 3
    list [set a()] [set a(1)] [set a($)] [unset a() a(1); lindex [array names a] 0]
} -cleanup {unset a} -result [list 1 2 3 {$}]


# Tests compile-15.* cover Tcl Bug 633204
test compile-15.1 {proper TCL_RETURN code from [return]} {
606
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
test compile-16.16.$noComp {TclCompileScript: word expansion} $constraints {
    run {list x {*}y z}
} {x y z}
test compile-16.17.$noComp {TclCompileScript: word expansion} $constraints {
    run {list {*}x y z}
} {x y z}

# These tests note that expansion can in theory cause the number of arguments
# to a command to exceed INT_MAX, which is as big as objc is allowed to get.

#
# In practice, it seems we will run out of memory before we confront this
# issue. Note that compiled operations run out of memory at smaller objc
# values than direct string evaluation.
#
# These tests are constrained as knownBug because they are likely to cause
# memory allocation panics somewhere, and we don't want panics in the test
# suite.
#
test compile-16.18.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<10}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<10}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {1<<20}]







|
|
>

|
|
|

|
|
|







538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
test compile-16.16.$noComp {TclCompileScript: word expansion} $constraints {
    run {list x {*}y z}
} {x y z}
test compile-16.17.$noComp {TclCompileScript: word expansion} $constraints {
    run {list {*}x y z}
} {x y z}

# These tests note that expansion can in theory cause the number of
# arguments to a command to exceed INT_MAX, which is as big as objc
# is allowed to get.
#
# In practice, it seems we will run out of memory before we confront
# this issue.  Note that compiled operations run out of memory at
# smaller objc values than direct string evaluation.
#
# These tests are constrained as knownBug because they are likely
# to cause memory allocation panics somewhere, and we don't want
# panics in the test suite.
#
test compile-16.18.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<10}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<10}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {1<<20}]
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
test compile-16.24.$noComp {
    Bug 1638414: bad list constant as first expanded term
} -constraints $constraints -body {
    run "{*}\"\{foo bar\""
} -returnCodes error -result {unmatched open brace in list}
}	;# End of noComp loop

# These tests are messy because it wrecks the interpreter it runs in!  They
# demonstrate issues arising from [FRQ 1101710]
test compile-17.1 {Command interpretation binding for compiled code} -constraints knownBug -setup {
    set i [interp create]
} -body {
    $i eval {
	if 1 {
	    expr [
		proc expr args {return substituted}







|
|







603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
test compile-16.24.$noComp {
    Bug 1638414: bad list constant as first expanded term
} -constraints $constraints -body {
    run "{*}\"\{foo bar\""
} -returnCodes error -result {unmatched open brace in list}
}	;# End of noComp loop

# These tests are messy because it wrecks the interpreter it runs in!
# They demonstrate issues arising from [FRQ 1101710]
test compile-17.1 {Command interpretation binding for compiled code} -constraints knownBug -setup {
    set i [interp create]
} -body {
    $i eval {
	if 1 {
	    expr [
		proc expr args {return substituted}
709
710
711
712
713
714
715
716
717
718
719
720
catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







<
<
<
<
<
642
643
644
645
646
647
648





catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}
::tcltest::cleanupTests
return





Changes to tests/dstring.test.

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
test dstring-2.12 {appending list elements} testdstring {
    testdstring free
    testdstring append x -1
    testdstring element #
    testdstring get
} {x #}
test dstring-2.13 {appending list elements} testdstring {
    # This test checks the sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append "x " -1
    testdstring element #
    testdstring get
} {x #}
test dstring-2.14 {appending list elements} testdstring {
    testdstring free
    testdstring append "  " -1
    testdstring element #
    testdstring get
} {  {#}}
test dstring-2.15 {appending list elements} testdstring {
    # This test checks the sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append "x  " -1
    testdstring element #
    testdstring get
} {x  #}

test dstring-3.1 {nested sublists} testdstring {
    testdstring free
    testdstring start
    testdstring element foo
    testdstring element bar
    testdstring end







|





|
<
<
<
<
<
<
<
<
<
<
<
<
<
<







126
127
128
129
130
131
132
133
134
135
136
137
138
139














140
141
142
143
144
145
146
test dstring-2.12 {appending list elements} testdstring {
    testdstring free
    testdstring append x -1
    testdstring element #
    testdstring get
} {x #}
test dstring-2.13 {appending list elements} testdstring {
    # This test shows lack of sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append "x " -1
    testdstring element #
    testdstring get
} {x {#}}















test dstring-3.1 {nested sublists} testdstring {
    testdstring free
    testdstring start
    testdstring element foo
    testdstring element bar
    testdstring end
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    testdstring start
    testdstring append x -1
    testdstring element #
    testdstring end
    testdstring get
} {x {x #}}
test dstring-3.10 {appending list elements} testdstring {
    # This test checks the sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append x -1
    testdstring start
    testdstring append "x " -1
    testdstring element #
    testdstring end
    testdstring get
} {x {x #}}
test dstring-3.11 {appending list elements} testdstring {
    testdstring free
    testdstring append x -1
    testdstring start
    testdstring append "  " -1
    testdstring element #
    testdstring end
    testdstring get
} {x {  {#}}}
test dstring-3.12 {appending list elements} testdstring {
    # This test checks the sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append x -1
    testdstring start
    testdstring append "x  " -1
    testdstring element #
    testdstring end
    testdstring get
} {x {x  #}}

test dstring-4.1 {truncation} testdstring {
    testdstring free
    testdstring append "abcdefg" -1
    testdstring trunc 3
    list [testdstring get] [testdstring length]
} {abc 3}







|








|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239




















240
241
242
243
244
245
246
    testdstring start
    testdstring append x -1
    testdstring element #
    testdstring end
    testdstring get
} {x {x #}}
test dstring-3.10 {appending list elements} testdstring {
    # This test shows lack of sophistication in Tcl_DStringAppendElement's
    # decision about whether #-quoting can be disabled.
    testdstring free
    testdstring append x -1
    testdstring start
    testdstring append "x " -1
    testdstring element #
    testdstring end
    testdstring get
} {x {x {#}}}





















test dstring-4.1 {truncation} testdstring {
    testdstring free
    testdstring append "abcdefg" -1
    testdstring trunc 3
    list [testdstring get] [testdstring length]
} {abc 3}

Changes to tests/encoding.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# This file contains a collection of tests for tclEncoding.c
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2

namespace eval ::tcl::test::encoding {
    variable x

namespace import -force ::tcltest::*

|
|




|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# This file contains a collection of tests for tclEncoding.c
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2

namespace eval ::tcl::test::encoding {
    variable x

namespace import -force ::tcltest::*
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
proc runtests {} {

    variable x

# Some tests require the testencoding command
testConstraint testencoding [llength [info commands testencoding]]
testConstraint exec [llength [info commands exec]]
testConstraint Uesc [expr {"\U0041" eq "A"}]

# TclInitEncodingSubsystem is tested by the rest of this file
# TclFinalizeEncodingSubsystem is not currently tested

test encoding-1.1 {Tcl_GetEncoding: system encoding} {testencoding} {
    testencoding create foo [namespace origin toutf] [namespace origin fromutf]
    set old [encoding system]
    encoding system foo







<
|







27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
proc runtests {} {

    variable x

# Some tests require the testencoding command
testConstraint testencoding [llength [info commands testencoding]]
testConstraint exec [llength [info commands exec]]


# TclInitEncodingSubsystem is tested by the rest of this file
# TclFinalizeEncodingSubsystem is not currently tested

test encoding-1.1 {Tcl_GetEncoding: system encoding} {testencoding} {
    testencoding create foo [namespace origin toutf] [namespace origin fromutf]
    set old [encoding system]
    encoding system foo
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    encoding convertto jis0208 \u4e4e
} {8C}
test encoding-2.2 {Tcl_FreeEncoding: refcount != 0} {testencoding} {
    set system [encoding system]
    set path [encoding dirs]
    encoding system shiftjis		;# incr ref count
    encoding dirs [list [pwd]]
    set x [encoding convertto shiftjis \u4E4E]	;# old one found
    encoding system iso8859-1
    llength shiftjis
    lappend x [catch {encoding convertto shiftjis \u4e4e} msg] $msg
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
    set x







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    encoding convertto jis0208 \u4e4e
} {8C}
test encoding-2.2 {Tcl_FreeEncoding: refcount != 0} {testencoding} {
    set system [encoding system]
    set path [encoding dirs]
    encoding system shiftjis		;# incr ref count
    encoding dirs [list [pwd]]
    set x [encoding convertto shiftjis \u4e4e]	;# old one found   
    encoding system iso8859-1
    llength shiftjis
    lappend x [catch {encoding convertto shiftjis \u4e4e} msg] $msg
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
    set x
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

test encoding-8.1 {Tcl_ExternalToUtf} {
    set f [open [file join [temporaryDirectory] dummy] w]
    fconfigure $f -translation binary -encoding iso8859-1
    puts -nonewline $f "ab\x8c\xc1g"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding shiftjis
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    set x
} "ab\u4e4eg"

test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

test encoding-8.1 {Tcl_ExternalToUtf} {
    set f [open [file join [temporaryDirectory] dummy] w]
    fconfigure $f -translation binary -encoding iso8859-1
    puts -nonewline $f "ab\x8c\xc1g"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding shiftjis    
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    set x
} "ab\u4e4eg"

test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
}

test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
    set system [encoding system]
    set path [encoding dirs]
    encoding system iso8859-1
    encoding dirs {}
    llength jis0208	;# Shimmer any cached Tcl_Encoding in shared literal
    set x [list [catch {encoding convertto jis0208 \u4e4e} msg] $msg]
    encoding dirs $path
    encoding system $system
    lappend x [encoding convertto jis0208 \u4e4e]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xa1







|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
}

test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
    set system [encoding system]
    set path [encoding dirs]
    encoding system iso8859-1
    encoding dirs {}
    llength jis0208
    set x [list [catch {encoding convertto jis0208 \u4e4e} msg] $msg]
    encoding dirs $path
    encoding system $system
    lappend x [encoding convertto jis0208 \u4e4e]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xa1
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    set path [encoding dirs]
    encoding system iso8859-1
    cd [temporaryDirectory]
    encoding dirs [file join tmp encoding]
    makeDirectory tmp
    makeDirectory [file join tmp encoding]
    set f [open [file join tmp encoding splat.enc] w]
    fconfigure $f -translation binary
    puts $f "abcdefghijklmnop"
    close $f
    set x [list [catch {encoding convertto splat \u4e4e} msg] $msg]
    file delete [file join [temporaryDirectory] tmp encoding splat.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp
    cd [workingDirectory]
    encoding dirs $path
    encoding system $system
    set x
} {1 {invalid encoding file "splat"}}

# OpenEncodingFile is fully tested by the rest of the tests in this file.

test encoding-12.1 {LoadTableEncoding: normal encoding} {
    set x [encoding convertto iso8859-3 \u0120]
    append x [encoding convertto iso8859-3 \xD5]
    append x [encoding convertfrom iso8859-3 \xD5]
} "\xd5?\u120"
test encoding-12.2 {LoadTableEncoding: single-byte encoding} {
    set x [encoding convertto iso8859-3 ab\u0120g]
    append x [encoding convertfrom iso8859-3 ab\xD5g]
} "ab\xd5gab\u120g"
test encoding-12.3 {LoadTableEncoding: multi-byte encoding} {
    set x [encoding convertto shiftjis ab\u4E4Eg]
    append x [encoding convertfrom shiftjis ab\x8c\xc1g]
} "ab\x8c\xc1gab\u4e4eg"
test encoding-12.4 {LoadTableEncoding: double-byte encoding} {
    set x [encoding convertto jis0208 \u4e4e\u3b1]
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A\u4e4e\u3b1"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol \u3b3]
    append x [encoding convertto symbol \u67]
    append x [encoding convertfrom symbol \x67]
} "\x67\x67\u3b3"
test encoding-12.6 {LoadTableEncoding: overflow in char value} Uesc {
    encoding convertto iso8859-3 \U010000
} "?"

test encoding-13.1 {LoadEscapeTable} {
    viewable [set x [encoding convertto iso2022 ab\u4e4e\u68d9g]]
} [viewable "ab\x1b\$B8C\x1b\$\(DD%\x1b(Bg"]

test encoding-14.1 {BinaryProc} {
    encoding convertto identity \x12\x34\x56\xff\x69
} "\x12\x34\x56\xc3\xbf\x69"

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 \xa3
} "\xc2\xa3"

test encoding-15.2 {UtfToUtfProc null character output} {
    set x \u0000
    set y [encoding convertto utf-8 \u0000]
    set y [bytestring $y]
    binary scan $y H* z
    list [string bytelength $x] [string bytelength $y] $z
} {2 1 00}

test encoding-15.3 {UtfToUtfProc null character input} {
    set x [bytestring \x00]
    set y [encoding convertfrom utf-8 $x]
    binary scan [encoding convertto identity $y] H* z
    list [string bytelength $x] [string bytelength $y] $z
} {1 2 c080}
test encoding-15.16 {UtfToUtfProc: Invalid 4-byte UTF-8, see [ed29806ba]} {
    set x \xF0\xA0\xA1\xC2
    set y [encoding convertfrom utf-8 \xF0\xA0\xA1\xC2]
    list [string length $x] $y
} "4 \xF0\xA0\xA1\xC2"

test encoding-16.1 {UnicodeToUtfProc} {
    set val [encoding convertfrom unicode NN]
    list $val [format %x [scan $val %c]]
} "\u4e4e 4e4e"

test encoding-17.1 {UtfToUnicodeProc} {







|















|
|
|


|
|


|











<
<
<
















|





|




<
<
<
<
<







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317





318
319
320
321
322
323
324
    set path [encoding dirs]
    encoding system iso8859-1
    cd [temporaryDirectory]
    encoding dirs [file join tmp encoding]
    makeDirectory tmp
    makeDirectory [file join tmp encoding]
    set f [open [file join tmp encoding splat.enc] w]
    fconfigure $f -translation binary 
    puts $f "abcdefghijklmnop"
    close $f
    set x [list [catch {encoding convertto splat \u4e4e} msg] $msg]
    file delete [file join [temporaryDirectory] tmp encoding splat.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp
    cd [workingDirectory]
    encoding dirs $path
    encoding system $system
    set x
} {1 {invalid encoding file "splat"}}

# OpenEncodingFile is fully tested by the rest of the tests in this file.

test encoding-12.1 {LoadTableEncoding: normal encoding} {
    set x [encoding convertto iso8859-3 \u120]
    append x [encoding convertto iso8859-3 \ud5]
    append x [encoding convertfrom iso8859-3 \xd5]
} "\xd5?\u120"
test encoding-12.2 {LoadTableEncoding: single-byte encoding} {
    set x [encoding convertto iso8859-3 ab\u0120g] 
    append x [encoding convertfrom iso8859-3 ab\xd5g]
} "ab\xd5gab\u120g"
test encoding-12.3 {LoadTableEncoding: multi-byte encoding} {
    set x [encoding convertto shiftjis ab\u4e4eg] 
    append x [encoding convertfrom shiftjis ab\x8c\xc1g]
} "ab\x8c\xc1gab\u4e4eg"
test encoding-12.4 {LoadTableEncoding: double-byte encoding} {
    set x [encoding convertto jis0208 \u4e4e\u3b1]
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A\u4e4e\u3b1"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol \u3b3]
    append x [encoding convertto symbol \u67]
    append x [encoding convertfrom symbol \x67]
} "\x67\x67\u3b3"




test encoding-13.1 {LoadEscapeTable} {
    viewable [set x [encoding convertto iso2022 ab\u4e4e\u68d9g]]
} [viewable "ab\x1b\$B8C\x1b\$\(DD%\x1b(Bg"]

test encoding-14.1 {BinaryProc} {
    encoding convertto identity \x12\x34\x56\xff\x69
} "\x12\x34\x56\xc3\xbf\x69"

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 \xa3
} "\xc2\xa3"

test encoding-15.2 {UtfToUtfProc null character output} {
    set x \u0000
    set y [encoding convertto utf-8 \u0000]
    set y [encoding convertfrom identity $y]
    binary scan $y H* z
    list [string bytelength $x] [string bytelength $y] $z
} {2 1 00}

test encoding-15.3 {UtfToUtfProc null character input} {
    set x [encoding convertfrom identity \x00]
    set y [encoding convertfrom utf-8 $x]
    binary scan [encoding convertto identity $y] H* z
    list [string bytelength $x] [string bytelength $y] $z
} {1 2 c080}






test encoding-16.1 {UnicodeToUtfProc} {
    set val [encoding convertfrom unicode NN]
    list $val [format %x [scan $val %c]]
} "\u4e4e 4e4e"

test encoding-17.1 {UtfToUnicodeProc} {
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
	    set f [open $from.chars]
	    fconfigure $f -encoding $from
	    set out [open $from.$to.tcltestout w]
	    fconfigure $out -encoding $to
	    puts -nonewline $out [read $f]
	    close $out
	    close $f

	    # then compare $to.chars <=> $from.to.tcltestout as binary.
	    set fa [open $to.chars]
	    fconfigure $fa -encoding binary
	    set fb [open $from.$to.tcltestout]
	    fconfigure $fb -encoding binary
	    set diff [channel-diff $fa $fb]
	    close $fa
	    close $fb

	    # Difference should be empty.
	    set diff
	} {}
    }
}

testConstraint testgetdefenc [llength [info commands testgetdefenc]]

test encoding-26.0 {Tcl_GetDefaultEncodingDir} -constraints {
    testgetdefenc
} -setup {
     set origDir [testgetdefenc]
     testsetdefenc slappy
} -body {
     testgetdefenc
} -cleanup {
     testsetdefenc $origDir







|








|









|







573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
	    set f [open $from.chars]
	    fconfigure $f -encoding $from
	    set out [open $from.$to.tcltestout w]
	    fconfigure $out -encoding $to
	    puts -nonewline $out [read $f]
	    close $out
	    close $f
	    
	    # then compare $to.chars <=> $from.to.tcltestout as binary.
	    set fa [open $to.chars]
	    fconfigure $fa -encoding binary
	    set fb [open $from.$to.tcltestout]
	    fconfigure $fb -encoding binary
	    set diff [channel-diff $fa $fb]
	    close $fa
	    close $fb
	    
	    # Difference should be empty.
	    set diff
	} {}
    }
}

testConstraint testgetdefenc [llength [info commands testgetdefenc]]

test encoding-26.0 {Tcl_GetDefaultEncodingDir} -constraints {
    testgetdefenc 
} -setup {
     set origDir [testgetdefenc]
     testsetdefenc slappy
} -body {
     testgetdefenc
} -cleanup {
     testsetdefenc $origDir

Changes to tests/env.test.

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
        lrem names COMSPEC
	lrem names ComSpec
	lrem names ""
    }
    foreach name {
	TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
	SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
	DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM
	__CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
	CommonProgramFiles ProgramFiles CommonProgramW6432 ProgramW6432
    } {
	lrem names $name
    }
    foreach p $names {
	puts "[mangle $p]=[mangle $env($p)]"







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
        lrem names COMSPEC
	lrem names ComSpec
	lrem names ""
    }
    foreach name {
	TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
	SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
	DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
	__CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
	CommonProgramFiles ProgramFiles CommonProgramW6432 ProgramW6432
    } {
	lrem names $name
    }
    foreach p $names {
	puts "[mangle $p]=[mangle $env($p)]"
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
set env2 [array get env]
foreach name [array names env] {
    # Keep some environment variables that support operation of the tcltest
    # package.
    if {[string toupper $name] ni {
	TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH
	SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
	DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM
	SECURITYSESSIONID LANG WINDIR TERM
	CONNOMPROGRAMFILES PROGRAMFILES COMMONPROGRAMW6432 PROGRAMW6432
    }} {
	unset env($name)
    }
}








|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
set env2 [array get env]
foreach name [array names env] {
    # Keep some environment variables that support operation of the tcltest
    # package.
    if {[string toupper $name] ni {
	TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH
	SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
	DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
	SECURITYSESSIONID LANG WINDIR TERM
	CONNOMPROGRAMFILES PROGRAMFILES COMMONPROGRAMW6432 PROGRAMW6432
    }} {
	unset env($name)
    }
}

Changes to tests/event.test.

500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
test event-11.4 {Tcl_VwaitCmd procedure} {} {
    foreach i [after info] {
	after cancel $i
    }
    after 10; update; # On Mac make sure update won't take long
    after 100 {set x x-done}
    after 200 {set y y-done}
    after 400 {set z z-done}
    after idle {set q q-done}
    set x before
    set y before
    set z before
    set q before
    list [vwait y] $x $y $z $q
} {{} x-done y-done before q-done}







|







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
test event-11.4 {Tcl_VwaitCmd procedure} {} {
    foreach i [after info] {
	after cancel $i
    }
    after 10; update; # On Mac make sure update won't take long
    after 100 {set x x-done}
    after 200 {set y y-done}
    after 300 {set z z-done}
    after idle {set q q-done}
    set x before
    set y before
    set z before
    set q before
    list [vwait y] $x $y $z $q
} {{} x-done y-done before q-done}

Changes to tests/exec.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
70
71
72
73
74
75
76
77
78
79
80
81
# Commands covered:  exec
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import -force ::tcltest::*

# All tests require the "exec" command.
# Skip them if exec is not defined.
testConstraint exec [llength [info commands exec]]
unset -nocomplain path

# Utilities that are like bourne shell stalwarts, but cross-platform.
set path(echo) [makeFile {
    puts -nonewline [lindex $argv 0]
    foreach str [lrange $argv 1 end] {
	puts -nonewline " $str"
    }
    puts {}
    exit
} echo]

set path(echo2) [makeFile {
    puts stdout [join $argv]
    puts stderr [lindex $argv 1]
    exit
} echo2]

set path(cat) [makeFile {
    if {$argv == {}} {
	set argv -
    }
    fconfigure stdout -translation binary
    foreach name $argv {
	if {$name == "-"} {
	    set f stdin
	} elseif {[catch {open $name r} f] != 0} {
	    puts stderr $f
	    continue
	}
	fconfigure $f -translation binary
	while {[eof $f] == 0} {
	    puts -nonewline [read $f]
	}
	if {$f != "stdin"} {
	    close $f
	}
    }
    exit
} cat]

set path(wc) [makeFile {
    set data [read stdin]
    set lines [regsub -all "\n" $data {} dummy]
    set words [regsub -all "\[^ \t\n]+" $data {} dummy]
    set chars [string length $data]
    puts [format "%8.d%8.d%8.d" $lines $words $chars]
    exit
} wc]

set path(sh) [makeFile {
    if {[lindex $argv 0] != "-c"} {
	error "sh: unexpected arguments $argv"
    }
    set cmd [lindex $argv 1]
    lappend cmd ";"

    set newcmd {}

    foreach arg $cmd {
	if {$arg == ";"} {
	    eval exec >@stdout 2>@stderr [list [info nameofexecutable]] $newcmd
	    set newcmd {}
	    continue
	}
	if {$arg == "1>&2"} {


|
|
|





|
|








<
<








>





>




<







<









>








>








|







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
# Commands covered:  exec
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import -force ::tcltest::*

# All tests require the "exec" command.
# Skip them if exec is not defined.
testConstraint exec [llength [info commands exec]]
unset -nocomplain path


set path(echo) [makeFile {
    puts -nonewline [lindex $argv 0]
    foreach str [lrange $argv 1 end] {
	puts -nonewline " $str"
    }
    puts {}
    exit
} echo]

set path(echo2) [makeFile {
    puts stdout [join $argv]
    puts stderr [lindex $argv 1]
    exit
} echo2]

set path(cat) [makeFile {
    if {$argv == {}} {
	set argv -
    }

    foreach name $argv {
	if {$name == "-"} {
	    set f stdin
	} elseif {[catch {open $name r} f] != 0} {
	    puts stderr $f
	    continue
	}

	while {[eof $f] == 0} {
	    puts -nonewline [read $f]
	}
	if {$f != "stdin"} {
	    close $f
	}
    }
    exit
} cat]

set path(wc) [makeFile {
    set data [read stdin]
    set lines [regsub -all "\n" $data {} dummy]
    set words [regsub -all "\[^ \t\n]+" $data {} dummy]
    set chars [string length $data]
    puts [format "%8.d%8.d%8.d" $lines $words $chars]
    exit
} wc]

set path(sh) [makeFile {
    if {[lindex $argv 0] != "-c"} {
	error "sh: unexpected arguments $argv"
    }
    set cmd [lindex $argv 1]
    lappend cmd ";"

    set newcmd {}
    
    foreach arg $cmd {
	if {$arg == ";"} {
	    eval exec >@stdout 2>@stderr [list [info nameofexecutable]] $newcmd
	    set newcmd {}
	    continue
	}
	if {$arg == "1>&2"} {
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
120
121
122
123
124
125
126
127
128
129
    if {[lindex $argv 0] != "-c"} {
	error "sh: unexpected arguments $argv"
    }
    set cmd [lindex $argv 1]
    lappend cmd ";"

    set newcmd {}

    foreach arg $cmd {
	if {$arg == ";"} {
	    eval exec -ignorestderr >@stdout [list [info nameofexecutable]] $newcmd
	    set newcmd {}
	    continue
	}
	lappend newcmd $arg
    }
    exit
} sh2]

set path(sleep) [makeFile {
    after [expr $argv*1000]
    exit
} sleep]

set path(exit) [makeFile {
    exit $argv
} exit]

proc readfile filename {
    set f [open $filename]
    set d [read $f]
    close $f
    return [string trimright $d \n]
}

# ----------------------------------------------------------------------
# Basic operations.

test exec-1.1 {basic exec operation} {exec} {
    exec [interpreter] $path(echo) a b c
} "a b c"
test exec-1.2 {pipelining} {exec stdio} {
    exec [interpreter] $path(echo) a b c d | [interpreter] $path(cat) | [interpreter] $path(cat)







|










>




>




<
<
<
<
<
<
<
<







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
120
121
122
123
    if {[lindex $argv 0] != "-c"} {
	error "sh: unexpected arguments $argv"
    }
    set cmd [lindex $argv 1]
    lappend cmd ";"

    set newcmd {}
    
    foreach arg $cmd {
	if {$arg == ";"} {
	    eval exec -ignorestderr >@stdout [list [info nameofexecutable]] $newcmd
	    set newcmd {}
	    continue
	}
	lappend newcmd $arg
    }
    exit
} sh2]

set path(sleep) [makeFile {
    after [expr $argv*1000]
    exit
} sleep]

set path(exit) [makeFile {
    exit $argv
} exit]









# Basic operations.

test exec-1.1 {basic exec operation} {exec} {
    exec [interpreter] $path(echo) a b c
} "a b c"
test exec-1.2 {pipelining} {exec stdio} {
    exec [interpreter] $path(echo) a b c d | [interpreter] $path(cat) | [interpreter] $path(cat)
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
} {Sample text}
test exec-2.4 {redirecting input from immediate source} {exec stdio} {
    exec [interpreter] $path(cat) | [interpreter] $path(cat) << "Sample text"
} {Sample text}
test exec-2.5 {redirecting input from immediate source} {exec} {
    exec [interpreter] $path(cat) "<<Joined to arrows"
} {Joined to arrows}
test exec-2.6 {redirecting input from immediate source, with UTF} -setup {
    set sysenc [encoding system]
    encoding system iso8859-1
    proc quotenonascii s {
	regsub -all {\[|\\|\]} $s {\\&} s
	regsub -all "\[\u007f-\uffff\]" $s \
	    {[apply {c {format {\u%04x} [scan $c %c]}} &]} s
	return [subst -novariables $s]
    }
} -constraints {exec} -body {
    # If this fails, it may give back: "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"

    # If it does, this means that the UTF -> external conversion did not occur
    # before writing out the temp file.
    quotenonascii [exec [interpreter] $path(cat) << "\uE9\uE0\uFC\uF1"]
} -cleanup {
    encoding system $sysenc
    rename quotenonascii {}
} -result {\u00e9\u00e0\u00fc\u00f1}

# I/O redirection: output to file.

set path(gorp.file) [makeFile {} gorp.file]
file delete $path(gorp.file)

test exec-3.1 {redirecting output to file} {exec} {







|
<
<
<
<
<
<
<
<
<
|
>
|
|
|
|
<
<
<







146
147
148
149
150
151
152
153









154
155
156
157
158
159



160
161
162
163
164
165
166
} {Sample text}
test exec-2.4 {redirecting input from immediate source} {exec stdio} {
    exec [interpreter] $path(cat) | [interpreter] $path(cat) << "Sample text"
} {Sample text}
test exec-2.5 {redirecting input from immediate source} {exec} {
    exec [interpreter] $path(cat) "<<Joined to arrows"
} {Joined to arrows}
test exec-2.6 {redirecting input from immediate source, with UTF} {exec} {









    # If this fails, it may give back:
    # "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"
    # If it does, this means that the UTF -> external conversion did not 
    # occur before writing out the temp file.
    exec [interpreter] $path(cat) << "\uE9\uE0\uFC\uF1"
} "\uE9\uE0\uFC\uF1"




# I/O redirection: output to file.

set path(gorp.file) [makeFile {} gorp.file]
file delete $path(gorp.file)

test exec-3.1 {redirecting output to file} {exec} {
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
} "Line 1\nMore text\nEven more\nLine 3"

# I/O redirection: output and stderr to file.

file delete $path(gorp.file)

test exec-4.1 {redirecting output and stderr to file} {exec} {
    exec [interpreter] $path(echo) "test output" >& $path(gorp.file)
    exec [interpreter] $path(cat) $path(gorp.file)
} "test output"
test exec-4.2 {redirecting output and stderr to file} {exec} {
    list [exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" >&$path(gorp.file)] \
	    [exec [interpreter] $path(cat) $path(gorp.file)]
} {{} {foo bar}}
test exec-4.3 {redirecting output and stderr to file} {exec} {
    exec [interpreter] $path(echo) "first line" > $path(gorp.file)
    list [exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" >>&$path(gorp.file)] \
	    [exec [interpreter] $path(cat) $path(gorp.file)]
} "{} {first line\nfoo bar}"
test exec-4.4 {redirecting output and stderr to file} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "Line 1"
    flush $f
    exec [interpreter] $path(echo) "More text" >&@ $f
    exec [interpreter] $path(echo) >&@$f "Even more"
    puts $f "Line 3"
    close $f
    exec [interpreter] $path(cat) $path(gorp.file)
} "Line 1\nMore text\nEven more\nLine 3"
test exec-4.5 {redirecting output and stderr to file} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "Line 1"
    flush $f
    exec >&@ $f [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2"
    exec >&@$f [interpreter] $path(sh) -c "\"$path(echo)\" xyzzy 1>&2"
    puts $f "Line 3"
    close $f
    exec [interpreter] $path(cat) $path(gorp.file)
} "Line 1\nfoo bar\nxyzzy\nLine 3"

# I/O redirection: input from file.

if {[testConstraint exec]} {
    exec [interpreter] $path(echo) "Just a few thoughts" > $path(gorp.file)
}







|
|


|
|



|
|


|


|
|


|


|


|
|


|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
} "Line 1\nMore text\nEven more\nLine 3"

# I/O redirection: output and stderr to file.

file delete $path(gorp.file)

test exec-4.1 {redirecting output and stderr to file} {exec} {
    exec [interpreter] "$path(echo)" "test output" >& $path(gorp.file)
    exec [interpreter] "$path(cat)" "$path(gorp.file)"
} "test output"
test exec-4.2 {redirecting output and stderr to file} {exec} {
    list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" >&$path(gorp.file)] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
} {{} {foo bar}}
test exec-4.3 {redirecting output and stderr to file} {exec} {
    exec [interpreter] $path(echo) "first line" > $path(gorp.file)
    list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" >>&$path(gorp.file)] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
} "{} {first line\nfoo bar}"
test exec-4.4 {redirecting output and stderr to file} {exec} {
    set f [open "$path(gorp.file)" w]
    puts $f "Line 1"
    flush $f
    exec [interpreter] "$path(echo)" "More text" >&@ $f
    exec [interpreter] "$path(echo)" >&@$f "Even more"
    puts $f "Line 3"
    close $f
    exec [interpreter] "$path(cat)" "$path(gorp.file)"
} "Line 1\nMore text\nEven more\nLine 3"
test exec-4.5 {redirecting output and stderr to file} {exec} {
    set f [open "$path(gorp.file)" w]
    puts $f "Line 1"
    flush $f
    exec >&@ $f [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2"
    exec >&@$f [interpreter] "$path(sh)" -c "\"$path(echo)\" xyzzy 1>&2"
    puts $f "Line 3"
    close $f
    exec [interpreter] "$path(cat)" "$path(gorp.file)"
} "Line 1\nfoo bar\nxyzzy\nLine 3"

# I/O redirection: input from file.

if {[testConstraint exec]} {
    exec [interpreter] $path(echo) "Just a few thoughts" > $path(gorp.file)
}
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324

325

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
} {Just a few thoughts}
test exec-5.4 {redirecting input from file} {exec stdio} {
    exec < $path(gorp.file) [interpreter] $path(cat) | [interpreter] $path(cat)
} {Just a few thoughts}
test exec-5.5 {redirecting input from file} {exec} {
    exec [interpreter] $path(cat) <$path(gorp.file)
} {Just a few thoughts}
test exec-5.6 {redirecting input from file} -constraints {exec} -body {
    set f [open $path(gorp.file) r]
    exec [interpreter] $path(cat) <@ $f
} -cleanup {
    close $f

} -result {Just a few thoughts}
test exec-5.7 {redirecting input from file} -constraints {exec} -body {
    set f [open $path(gorp.file) r]
    exec <@$f [interpreter] $path(cat)
} -cleanup {
    close $f

} -result {Just a few thoughts}

# I/O redirection: standard error through a pipeline.

test exec-6.1 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar" |& [interpreter] $path(cat)
} "foo bar"
test exec-6.2 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" |& [interpreter] $path(cat)
} "foo bar"
test exec-6.3 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" \
	|& [interpreter] $path(sh) -c "\"$path(echo)\" second msg 1>&2 ; \"$path(cat)\"" |& [interpreter] $path(cat)
} "second msg\nfoo bar"

# I/O redirection: combinations.

set path(gorp.file2) [makeFile {} gorp.file2]

test exec-7.1 {multiple I/O redirections} {exec} {
    exec << "command input" > $path(gorp.file2) [interpreter] $path(cat) < $path(gorp.file)
    exec [interpreter] $path(cat) $path(gorp.file2)
} {Just a few thoughts}
test exec-7.2 {multiple I/O redirections} {exec} {
    exec < $path(gorp.file) << "command input" [interpreter] $path(cat)
} {command input}

# Long input to command and output from command.

set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n"
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
test exec-8.1 {long input and output} {exec} {
    exec [interpreter] $path(cat) << $a
} $a

# More than 20 arguments to exec.

test exec-8.2 {long input and output} {exec} {
    exec [interpreter] $path(echo) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23}

# Commands that return errors.

test exec-9.1 {commands returning errors} {exec} {
    set x [catch {exec gorp456} msg]
    list $x [string tolower $msg] [string tolower $errorCode]
} {1 {couldn't execute "gorp456": no such file or directory} {posix enoent {no such file or directory}}}
test exec-9.2 {commands returning errors} {exec} {
    string tolower [list [catch {exec [interpreter] echo foo | foo123} msg] $msg $errorCode]
} {1 {couldn't execute "foo123": no such file or directory} {posix enoent {no such file or directory}}}
test exec-9.3 {commands returning errors} -constraints {exec stdio} -body {
    exec [interpreter] $path(sleep) 1 | [interpreter] $path(exit) 43 | [interpreter] $path(sleep) 1
} -returnCodes error -result {child process exited abnormally}
test exec-9.4 {commands returning errors} -constraints {exec stdio} -body {
    exec [interpreter] $path(exit) 43 | [interpreter] $path(echo) "foo bar"
} -returnCodes error -result {foo bar
child process exited abnormally}
test exec-9.5 {commands returning errors} -constraints {exec stdio} -body {
    exec gorp456 | [interpreter] echo a b c
} -returnCodes error -result {couldn't execute "gorp456": no such file or directory}
test exec-9.6 {commands returning errors} -constraints {exec} -body {
    exec [interpreter] $path(sh) -c "\"$path(echo)\" error msg 1>&2"
} -returnCodes error -result {error msg}
test exec-9.7 {commands returning errors} -constraints {exec stdio nonPortable} -body {
    # This test can fail easily on multiprocessor machines
    exec [interpreter] $path(sh) -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1" \
	| [interpreter] $path(sh) -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1"
} -returnCodes error -result {error msg
error msg}

set path(err) [makeFile {} err]

test exec-9.8 {commands returning errors} -constraints {exec} -setup {
    set f [open $path(err) w]
    puts $f {
	puts stdout out
	puts stderr err
    }
    close $f
} -body {
    exec [interpreter] $path(err)
} -returnCodes error -result {out
err}

# Errors in executing the Tcl command, as opposed to errors in the processes
# that are invoked.

test exec-10.1 {errors in exec invocation} {exec} {
    list [catch {exec} msg] $msg
} {1 {wrong # args: should be "exec ?switches? arg ?arg ...?"}}
test exec-10.2 {errors in exec invocation} {exec} {
    list [catch {exec | cat} msg] $msg
} {1 {illegal use of | or |& in command}}







|

|
<

>
|
|

|
<

>
|




|


|


|
|















>








>

>













|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
>

>
|






<
|
|
|

|
|







254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362
363
364
365
} {Just a few thoughts}
test exec-5.4 {redirecting input from file} {exec stdio} {
    exec < $path(gorp.file) [interpreter] $path(cat) | [interpreter] $path(cat)
} {Just a few thoughts}
test exec-5.5 {redirecting input from file} {exec} {
    exec [interpreter] $path(cat) <$path(gorp.file)
} {Just a few thoughts}
test exec-5.6 {redirecting input from file} {exec} {
    set f [open $path(gorp.file) r]
    set result [exec [interpreter] $path(cat) <@ $f]

    close $f
    set result
} {Just a few thoughts}
test exec-5.7 {redirecting input from file} {exec} {
    set f [open $path(gorp.file) r]
    set result [exec <@$f [interpreter] $path(cat)]

    close $f
    set result
} {Just a few thoughts}

# I/O redirection: standard error through a pipeline.

test exec-6.1 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar" |& [interpreter] "$path(cat)"
} "foo bar"
test exec-6.2 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" |& [interpreter] "$path(cat)"
} "foo bar"
test exec-6.3 {redirecting stderr through a pipeline} {exec stdio} {
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
	|& [interpreter] "$path(sh)" -c "\"$path(echo)\" second msg 1>&2 ; \"$path(cat)\"" |& [interpreter] "$path(cat)"
} "second msg\nfoo bar"

# I/O redirection: combinations.

set path(gorp.file2) [makeFile {} gorp.file2]

test exec-7.1 {multiple I/O redirections} {exec} {
    exec << "command input" > $path(gorp.file2) [interpreter] $path(cat) < $path(gorp.file)
    exec [interpreter] $path(cat) $path(gorp.file2)
} {Just a few thoughts}
test exec-7.2 {multiple I/O redirections} {exec} {
    exec < $path(gorp.file) << "command input" [interpreter] $path(cat)
} {command input}

# Long input to command and output from command.

set a "0123456789 xxxxxxxxx abcdefghi ABCDEFGHIJK\n"
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
set a [concat $a $a $a $a]
test exec-8.1 {long input and output} {exec} {
    exec [interpreter] $path(cat) << $a
} $a

# More than 20 arguments to exec.

test exec-8.2 {long input and output} {exec} {
    exec [interpreter] $path(echo) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23}

# Commands that return errors.

test exec-9.1 {commands returning errors} {exec} {
    set x [catch {exec gorp456} msg]
    list $x [string tolower $msg] [string tolower $errorCode]
} {1 {couldn't execute "gorp456": no such file or directory} {posix enoent {no such file or directory}}}
test exec-9.2 {commands returning errors} {exec} {
    string tolower [list [catch {exec [interpreter] echo foo | foo123} msg] $msg $errorCode]
} {1 {couldn't execute "foo123": no such file or directory} {posix enoent {no such file or directory}}}
test exec-9.3 {commands returning errors} {exec stdio} {
    list [catch {exec [interpreter] $path(sleep) 1 | [interpreter] $path(exit) 43 | [interpreter] $path(sleep) 1} msg] $msg
} {1 {child process exited abnormally}}
test exec-9.4 {commands returning errors} {exec stdio} {
    list [catch {exec [interpreter] $path(exit) 43 | [interpreter] $path(echo) "foo bar"} msg] $msg
} {1 {foo bar
child process exited abnormally}}
test exec-9.5 {commands returning errors} {exec stdio} {
    list [catch {exec gorp456 | [interpreter] echo a b c} msg] [string tolower $msg]
} {1 {couldn't execute "gorp456": no such file or directory}}
test exec-9.6 {commands returning errors} {exec} {
    list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2"} msg] $msg
} {1 {error msg}}
test exec-9.7 {commands returning errors} {exec stdio} {

    list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1" \
		    | [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1"} msg] $msg
} {1 {error msg
error msg}}

set path(err) [makeFile {} err]

test exec-9.8 {commands returning errors} {exec} {
    set f [open $path(err) w]
    puts $f {
	puts stdout out
	puts stderr err
    }
    close $f

    list [catch {exec [interpreter] $path(err)} msg] $msg
} {1 {out
err}}

# Errors in executing the Tcl command, as opposed to errors in the
# processes that are invoked.

test exec-10.1 {errors in exec invocation} {exec} {
    list [catch {exec} msg] $msg
} {1 {wrong # args: should be "exec ?switches? arg ?arg ...?"}}
test exec-10.2 {errors in exec invocation} {exec} {
    list [catch {exec | cat} msg] $msg
} {1 {illegal use of | or |& in command}}
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
-constraints exec \
-returnCodes 1 \
-body {exec echo test > ~non_existent_user/foo/bar} \
-result {user "non_existent_user" doesn't exist}
# Commands in background.

test exec-11.1 {commands in background} {exec} {
    set time [time {exec [interpreter] $path(sleep) 2 &}]
    expr {[lindex $time 0] < 1000000}
} 1
test exec-11.2 {commands in background} -constraints {exec} -body {
    exec [interpreter] $path(echo) a &b
} -result {a &b}
test exec-11.3 {commands in background} {exec} {
    llength [exec [interpreter] $path(sleep) 1 &]
} 1
test exec-11.4 {commands in background} {exec stdio} {
    llength [exec [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 &]
} 3
test exec-11.5 {commands in background} {exec} {
    set f [open $path(gorp.file) w]
    puts $f [list catch [list exec [info nameofexecutable] $path(echo) foo &]]
    close $f
    exec [interpreter] $path(gorp.file)
} foo

# Make sure that background commands are properly reaped when they
# eventually die.

if {[testConstraint exec] && [testConstraint nonPortable]} {
    after 1300
    exec [interpreter] $path(sleep) 1
}
test exec-12.1 {reaping background processes} {exec unix nonPortable} {

    for {set i 0} {$i < 20} {incr i} {
	exec echo foo > /dev/null &
    }
    after 1000
    catch {exec ps | fgrep "echo foo" | fgrep -v fgrep | wc} msg
    lindex $msg 0
} 0
test exec-12.2 {reaping background processes} {exec unix nonPortable} {

    exec sleep 2 | sleep 2 | sleep 2 &
    catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
    set x [lindex $msg 0]
    after 3000
    catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
    list $x [lindex $msg 0]
} {3 0}
test exec-12.3 {reaping background processes} {exec unix nonPortable} {

    exec sleep 1000 &
    exec sleep 1000 &
    set x [exec ps | fgrep "sleep" | fgrep -v fgrep]
    set pids {}
    foreach i [split $x \n] {
	lappend pids [lindex $i 0]
    }
    foreach i $pids {
	catch {exec kill -STOP $i}
    }
    catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
    set x [lindex $msg 0]

    foreach i $pids {
	catch {exec kill -KILL $i}
    }
    catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
    list $x [lindex $msg 0]
} {2 0}








|
|

|
|
|










|
|

|
|

|
<
|

|
>



|



|
>



|



|
>












>







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
-constraints exec \
-returnCodes 1 \
-body {exec echo test > ~non_existent_user/foo/bar} \
-result {user "non_existent_user" doesn't exist}
# Commands in background.

test exec-11.1 {commands in background} {exec} {
    set x [lindex [time {exec [interpreter] $path(sleep) 2 &}] 0]
    expr $x<1000000
} 1
test exec-11.2 {commands in background} {exec} {
    list [catch {exec [interpreter] $path(echo) a &b} msg] $msg
} {0 {a &b}}
test exec-11.3 {commands in background} {exec} {
    llength [exec [interpreter] $path(sleep) 1 &]
} 1
test exec-11.4 {commands in background} {exec stdio} {
    llength [exec [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 | [interpreter] $path(sleep) 1 &]
} 3
test exec-11.5 {commands in background} {exec} {
    set f [open $path(gorp.file) w]
    puts $f [list catch [list exec [info nameofexecutable] $path(echo) foo &]]
    close $f
    string compare "foo" [exec [interpreter] $path(gorp.file)]
} 0

# Make sure that background commands are properly reaped when
# they eventually die.

if {[testConstraint exec]} {

    exec [interpreter] $path(sleep) 3
}
test exec-12.1 {reaping background processes} \
	{exec unix nonPortable} {
    for {set i 0} {$i < 20} {incr i} {
	exec echo foo > /dev/null &
    }
    exec sleep 1
    catch {exec ps | fgrep "echo foo" | fgrep -v fgrep | wc} msg
    lindex $msg 0
} 0
test exec-12.2 {reaping background processes} \
	{exec unix nonPortable} {
    exec sleep 2 | sleep 2 | sleep 2 &
    catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
    set x [lindex $msg 0]
    exec sleep 3
    catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
    list $x [lindex $msg 0]
} {3 0}
test exec-12.3 {reaping background processes} \
	{exec unix nonPortable} {
    exec sleep 1000 &
    exec sleep 1000 &
    set x [exec ps | fgrep "sleep" | fgrep -v fgrep]
    set pids {}
    foreach i [split $x \n] {
	lappend pids [lindex $i 0]
    }
    foreach i $pids {
	catch {exec kill -STOP $i}
    }
    catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
    set x [lindex $msg 0]

    foreach i $pids {
	catch {exec kill -KILL $i}
    }
    catch {exec ps | fgrep "sleep" | fgrep -v fgrep | wc} msg
    list $x [lindex $msg 0]
} {2 0}

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
    }
    -cleanup {
        removeFile $tmp
    }
    -result {1 {CHILDSTATUS {} 1073741823}}
}

test exec-13.6 {extended exit result codes: signalled} {
    -constraints {win}
    -setup {
        set tmp [makeFile {exit 0xC0000016} tmpfile.exec-13.6]
    }
    -body {
        list [catch {exec [interpreter] $tmp} err]\
            [lreplace $::errorCode 1 1 {}]







|







537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
    }
    -cleanup {
        removeFile $tmp
    }
    -result {1 {CHILDSTATUS {} 1073741823}}
}

test exec-13.6 {extended exit result codes: signalled} {   
    -constraints {win}
    -setup {
        set tmp [makeFile {exit 0xC0000016} tmpfile.exec-13.6]
    }
    -body {
        list [catch {exec [interpreter] $tmp} err]\
            [lreplace $::errorCode 1 1 {}]
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
    # Alas, the use of -ignorestderr is buried here :-(
    exec [interpreter] $path(sh2) -c [list $path(echo2) foo bar] 2>@1
} "foo bar\nbar"

# Redirecting standard error separately from standard output

test exec-15.1 {standard error redirection} {exec} {
    exec [interpreter] $path(echo) "First line" > $path(gorp.file)
    list [exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" 2> $path(gorp.file)] \
	    [exec [interpreter] $path(cat) $path(gorp.file)]
} {{} {foo bar}}
test exec-15.2 {standard error redirection} {exec stdio} {
    list [exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" \
	      | [interpreter] $path(echo) biz baz >$path(gorp.file) 2> $path(gorp.file2)] \
	[exec [interpreter] $path(cat) $path(gorp.file)] \
	[exec [interpreter] $path(cat) $path(gorp.file2)]
} {{} {biz baz} {foo bar}}
test exec-15.3 {standard error redirection} {exec stdio} {
    list [exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" \
	      | [interpreter] $path(echo) biz baz 2>$path(gorp.file) > $path(gorp.file2)] \
	[exec [interpreter] $path(cat) $path(gorp.file)] \
	[exec [interpreter] $path(cat) $path(gorp.file2)]
} {{} {foo bar} {biz baz}}
test exec-15.4 {standard error redirection} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "Line 1"
    flush $f
    exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" 2>@ $f
    puts $f "Line 3"
    close $f
    readfile $path(gorp.file)
} {Line 1
foo bar
Line 3}
test exec-15.5 {standard error redirection} {exec} {
    exec [interpreter] $path(echo) "First line" > "$path(gorp.file)"
    exec [interpreter] $path(sh) -c "\"$path(echo)\" foo bar 1>&2" 2>> "$path(gorp.file)"
    readfile $path(gorp.file)
} {First line
foo bar}
test exec-15.6 {standard error redirection} {exec stdio} {
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" > "$path(gorp.file2)" 2> "$path(gorp.file)" \
	    >& "$path(gorp.file)" 2> "$path(gorp.file2)" | [interpreter] "$path(echo)" biz baz
    list [exec [interpreter] "$path(cat)" "$path(gorp.file)"] [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
} {{biz baz} {foo bar}}
test exec-15.7 {standard error redirection 2>@1} {exec stdio} {
    # This redirects stderr output into normal result output from exec
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>@1
} {foo bar}

test exec-16.1 {flush output before exec} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "First line"
    exec [interpreter] $path(echo) "Second line" >@ $f
    puts $f "Third line"
    close $f
    readfile $path(gorp.file)
} {First line
Second line
Third line}
test exec-16.2 {flush output before exec} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "First line"
    exec [interpreter] << {puts stderr {Second line}} >&@ $f > $path(gorp.file2)
    puts $f "Third line"
    close $f
    readfile $path(gorp.file)
} {First line
Second line
Third line}

set path(script) [makeFile {} script]

test exec-17.1 { inheriting standard I/O } {exec} {







|
|
|


|
|
|
|


|
|
|
|


|


|


|




|
|
|


















|









|







574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
    # Alas, the use of -ignorestderr is buried here :-(
    exec [interpreter] $path(sh2) -c [list $path(echo2) foo bar] 2>@1
} "foo bar\nbar"

# Redirecting standard error separately from standard output

test exec-15.1 {standard error redirection} {exec} {
    exec [interpreter] "$path(echo)" "First line" > "$path(gorp.file)"
    list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2> "$path(gorp.file)"] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"]
} {{} {foo bar}}
test exec-15.2 {standard error redirection} {exec stdio} {
    list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
		| [interpreter] "$path(echo)" biz baz >$path(gorp.file) 2> "$path(gorp.file2)"] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
} {{} {biz baz} {foo bar}}
test exec-15.3 {standard error redirection} {exec stdio} {
    list [exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" \
	        | [interpreter] "$path(echo)" biz baz 2>$path(gorp.file) > "$path(gorp.file2)"] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file)"] \
	    [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
} {{} {foo bar} {biz baz}}
test exec-15.4 {standard error redirection} {exec} {
    set f [open "$path(gorp.file)" w]
    puts $f "Line 1"
    flush $f
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>@ $f
    puts $f "Line 3"
    close $f
    exec [interpreter] "$path(cat)" "$path(gorp.file)"
} {Line 1
foo bar
Line 3}
test exec-15.5 {standard error redirection} {exec} {
    exec [interpreter] "$path(echo)" "First line" > "$path(gorp.file)"
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>> "$path(gorp.file)"
    exec [interpreter] "$path(cat)" "$path(gorp.file)"
} {First line
foo bar}
test exec-15.6 {standard error redirection} {exec stdio} {
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" > "$path(gorp.file2)" 2> "$path(gorp.file)" \
	    >& "$path(gorp.file)" 2> "$path(gorp.file2)" | [interpreter] "$path(echo)" biz baz
    list [exec [interpreter] "$path(cat)" "$path(gorp.file)"] [exec [interpreter] "$path(cat)" "$path(gorp.file2)"]
} {{biz baz} {foo bar}}
test exec-15.7 {standard error redirection 2>@1} {exec stdio} {
    # This redirects stderr output into normal result output from exec
    exec [interpreter] "$path(sh)" -c "\"$path(echo)\" foo bar 1>&2" 2>@1
} {foo bar}

test exec-16.1 {flush output before exec} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "First line"
    exec [interpreter] $path(echo) "Second line" >@ $f
    puts $f "Third line"
    close $f
    exec [interpreter] $path(cat) $path(gorp.file)
} {First line
Second line
Third line}
test exec-16.2 {flush output before exec} {exec} {
    set f [open $path(gorp.file) w]
    puts $f "First line"
    exec [interpreter] << {puts stderr {Second line}} >&@ $f > $path(gorp.file2)
    puts $f "Third line"
    close $f
    exec [interpreter] $path(cat) $path(gorp.file)
} {First line
Second line
Third line}

set path(script) [makeFile {} script]

test exec-17.1 { inheriting standard I/O } {exec} {
719
720
721
722
723
724
725
726
727
728
729
foreach file {script gorp.file gorp.file2 echo echo2 cat wc sh sh2 sleep exit err} {
    removeFile $file
}
unset -nocomplain path

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







<
<
<
<
708
709
710
711
712
713
714




foreach file {script gorp.file gorp.file2 echo echo2 cat wc sh sh2 sleep exit err} {
    removeFile $file
}
unset -nocomplain path

::tcltest::cleanupTests
return




Changes to tests/execute.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# This file contains tests for the tclExecute.c source file. Tests appear in
# the same order as the C code that they test. The set of tests is currently
# incomplete since it currently includes only new tests for code changed for
# the addition of Tcl namespaces. Other execution-related tests appear in
# several other test files including namespace.test, basic.test, eval.test,
# for.test, etc.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

catch {namespace delete {*}[namespace children :: test_ns_*]}
|
|
|
|
|
|

|
|




|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# This file contains tests for the tclExecute.c source file. Tests appear
# in the same order as the C code that they test. The set of tests is
# currently incomplete since it currently includes only new tests for
# code changed for the addition of Tcl namespaces. Other execution-
# related tests appear in several other test files including
# namespace.test, basic.test, eval.test, for.test, etc.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

catch {namespace delete {*}[namespace children :: test_ns_*]}
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
# INST_CONCAT1 not tested
# INST_INVOKE_STK4 not tested
# INST_INVOKE_STK1 not tested
# INST_EVAL_STK not tested
# INST_EXPR_STK not tested

# INST_LOAD_SCALAR1

test execute-1.1 {TclExecuteByteCode, INST_LOAD_SCALAR1, small opnd} {
    proc foo {} {
	set x 1
	return $x
    }
    foo
} 1
test execute-1.2 {TclExecuteByteCode, INST_LOAD_SCALAR1, large opnd} {
    # Bug: 2243
    set body {}
    for {set i 0} {$i < 129} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	return $y
    }

    proc foo {} $body
    foo
} 1
test execute-1.3 {TclExecuteByteCode, INST_LOAD_SCALAR1, error} {
    proc foo {} {
	set x 1
	unset x







>

















>







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
# INST_CONCAT1 not tested
# INST_INVOKE_STK4 not tested
# INST_INVOKE_STK1 not tested
# INST_EVAL_STK not tested
# INST_EXPR_STK not tested

# INST_LOAD_SCALAR1

test execute-1.1 {TclExecuteByteCode, INST_LOAD_SCALAR1, small opnd} {
    proc foo {} {
	set x 1
	return $x
    }
    foo
} 1
test execute-1.2 {TclExecuteByteCode, INST_LOAD_SCALAR1, large opnd} {
    # Bug: 2243
    set body {}
    for {set i 0} {$i < 129} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	return $y
    }

    proc foo {} $body
    foo
} 1
test execute-1.3 {TclExecuteByteCode, INST_LOAD_SCALAR1, error} {
    proc foo {} {
	set x 1
	unset x
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
    for {set i 0} {$i < 256} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	return $y
    }

    proc foo {} $body
    foo
} 1
test execute-2.2 {TclExecuteByteCode, INST_LOAD_SCALAR4, error} {
    set body {}
    for {set i 0} {$i < 256} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	unset y
	return $y
    }

    proc foo {} $body
    list [catch {foo} msg] $msg
} {1 {can't read "y": no such variable}}


# INST_LOAD_SCALAR_STK not tested
# INST_LOAD_ARRAY4 not tested
# INST_LOAD_ARRAY1 not tested
# INST_LOAD_ARRAY_STK not tested
# INST_LOAD_STK not tested
# INST_STORE_SCALAR4 not tested







>













>



>







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
    for {set i 0} {$i < 256} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	return $y
    }

    proc foo {} $body
    foo
} 1
test execute-2.2 {TclExecuteByteCode, INST_LOAD_SCALAR4, error} {
    set body {}
    for {set i 0} {$i < 256} {incr i} {
	append body "set x$i x\n"
    }
    append body {
	set y 1
	unset y
	return $y
    }

    proc foo {} $body
    list [catch {foo} msg] $msg
} {1 {can't read "y": no such variable}}


# INST_LOAD_SCALAR_STK not tested
# INST_LOAD_ARRAY4 not tested
# INST_LOAD_ARRAY1 not tested
# INST_LOAD_ARRAY_STK not tested
# INST_LOAD_STK not tested
# INST_STORE_SCALAR4 not tested
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
    set e { [llength {}]+1 }
    set result {}
    interp create slave
    interp alias {} e slave expr
    lappend result [e $e]
    interp delete slave
    interp create slave
    interp alias {} e slave expr
    lappend result [e $e]
    interp delete slave
    set result
} {1 1}
test execute-6.13 {Tcl_ExprObj: exprcode epoch validation} {
    set e { [llength {}]+1 }
    set result {}







|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
    set e { [llength {}]+1 }
    set result {}
    interp create slave
    interp alias {} e slave expr
    lappend result [e $e]
    interp delete slave
    interp create slave
    interp alias {} e slave expr 
    lappend result [e $e]
    interp delete slave
    set result
} {1 1}
test execute-6.13 {Tcl_ExprObj: exprcode epoch validation} {
    set e { [llength {}]+1 }
    set result {}
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
    expr {int(0x1 * 1024 * 1024 * 1024 * 1024)}
} 0
test execute-7.34 {Wide int handling} {
    expr {wide(0x1) * 1024 * 1024 * 1024 * 1024}
} 1099511627776

test execute-8.1 {Stack protection} -setup {
    # If [Bug #804681] has not been properly taken care of, this should
    # segfault
    proc whatever args {llength $args}
    trace add variable ::errorInfo {write unset} whatever
} -body {
    expr {1+9/0}
} -cleanup {
    trace remove variable ::errorInfo {write unset} whatever
    rename whatever {}







|
|







884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
    expr {int(0x1 * 1024 * 1024 * 1024 * 1024)}
} 0
test execute-7.34 {Wide int handling} {
    expr {wide(0x1) * 1024 * 1024 * 1024 * 1024}
} 1099511627776

test execute-8.1 {Stack protection} -setup {
    # If [Bug #804681] has not been properly
    # taken care of, this should segfault
    proc whatever args {llength $args}
    trace add variable ::errorInfo {write unset} whatever
} -body {
    expr {1+9/0}
} -cleanup {
    trace remove variable ::errorInfo {write unset} whatever
    rename whatever {}
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
     interp recursionlimit {} 100
 } -cleanup {
     interp recursionlimit {} $limit
 } -result {too many nested evaluations (infinite loop?)}

test execute-8.3 {Stack restoration} -body {
    # Test for [Bug #1055676], correct restoration
    # of the stack top after the epoch is bumped and
    # the stack is grown in a call from a nested evaluation
     set arglst [string repeat "a " 1000]
     proc f {args} "f $arglst"
     proc run {} {
	 # bump the interp's epoch
	 rename ::set ::dummy
	 rename ::dummy ::set







|







911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
     interp recursionlimit {} 100
 } -cleanup {
     interp recursionlimit {} $limit
 } -result {too many nested evaluations (infinite loop?)}

test execute-8.3 {Stack restoration} -body {
    # Test for [Bug #1055676], correct restoration
    # of the stack top after the epoch is bumped and 
    # the stack is grown in a call from a nested evaluation
     set arglst [string repeat "a " 1000]
     proc f {args} "f $arglst"
     proc run {} {
	 # bump the interp's epoch
	 rename ::set ::dummy
	 rename ::dummy ::set
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
    rename foo {}
    rename FOO {}
} -result {}

test execute-9.1 {Interp result resetting [Bug 1522803]} {
    set c 0
    catch {
	catch {error foo}
	expr {1/$c}
    }
    if {[string match *foo* $::errorInfo]} {
	set result "Bad errorInfo: $::errorInfo"
    } else {
	set result SUCCESS
    }







|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
    rename foo {}
    rename FOO {}
} -result {}

test execute-9.1 {Interp result resetting [Bug 1522803]} {
    set c 0
    catch {
	catch {set foo}
	expr {1/$c}
    }
    if {[string match *foo* $::errorInfo]} {
	set result "Bad errorInfo: $::errorInfo"
    } else {
	set result SUCCESS
    }
991
992
993
994
995
996
997
998
999
catch {unset y}
catch {unset msg}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







<

996
997
998
999
1000
1001
1002

1003
catch {unset y}
catch {unset msg}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl

# End:

Changes to tests/expr.test.

6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
test expr-41.1 {exponent overflow} {
    expr 1.0e2147483630
} Inf
test expr-41.2 {exponent underflow} {
    expr 1.0e-2147483630
} 0.0

test expr-41.3 {exponent overflow} {
    expr 1e2147483647
} Inf
test expr-41.4 {exponent overflow} {
    expr 1e2147483648
} Inf
test expr-41.5 {exponent overflow} {
    expr 100e2147483645
} Inf
test expr-41.6 {exponent overflow} {
    expr 100e2147483646
} Inf
test expr-41.7 {exponent overflow} {
    expr 1.0e2147483647
} Inf
test expr-41.8 {exponent overflow} {
    expr 1.0e2147483648
} Inf
test expr-41.9 {exponent overflow} {
    expr 1.2e2147483647
} Inf
test expr-41.10 {exponent overflow} {
    expr 1.2e2147483648
} Inf

test expr-41.11 {exponent overflow} {
    expr 1e-2147483648
} 0.0
test expr-41.12 {exponent overflow} {
    expr 1e-2147483649
} 0.0
test expr-41.13 {exponent overflow} {
    expr 100e-2147483650
} 0.0
test expr-41.14 {exponent overflow} {
    expr 100e-2147483651
} 0.0 
test expr-41.15 {exponent overflow} {
    expr 1.0e-2147483648
} 0.0 
test expr-41.16 {exponent overflow} {
    expr 1.0e-2147483649
} 0.0 
test expr-41.17 {exponent overflow} {
    expr 1.23e-2147483646
} 0.0
test expr-41.18 {exponent overflow} {
    expr 1.23e-2147483647
} 0.0 

test expr-41.19 {numSigDigs == 0} {
    expr 0e309
} 0.0
test expr-41.20 {numSigDigs == 0} {
    expr 0e310
} 0.0
test expr-41.21 {negative zero, large exponent} {
    expr -0e309
} -0.0
test expr-41.22 {negative zero, large exponent} {
    expr -0e310
} -0.0
test expr-41.23 {floating point overflow on significand (Bug 1de6b0629e)} {
    expr 123[string repeat 0 309]1e-310
} 123.0

test expr-42.1 {denormals} ieeeFloatingPoint {
    expr 7e-324
} 5e-324

# TIP 114

test expr-43.1 {0b notation} {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







6832
6833
6834
6835
6836
6837
6838


































































6839
6840
6841
6842
6843
6844
6845
test expr-41.1 {exponent overflow} {
    expr 1.0e2147483630
} Inf
test expr-41.2 {exponent underflow} {
    expr 1.0e-2147483630
} 0.0



































































test expr-42.1 {denormals} ieeeFloatingPoint {
    expr 7e-324
} 5e-324

# TIP 114

test expr-43.1 {0b notation} {

Changes to tests/fCmd.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
testConstraint winVista 0
testConstraint win2000orXP 0
testConstraint winOlderThan2000 0
# Don't know how to determine this constraint correctly
testConstraint notNetworkFilesystem 0
testConstraint 95or98 [expr {[testConstraint 95] || [testConstraint 98]}]
testConstraint 2000orNewer [expr {![testConstraint 95or98]}]
testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::regver [package require registry 1.3.5]
	}]} {
	testConstraint reg 1
    }
}

set tmpspace /tmp;# default value
# Find a group that exists on this Unix system, or else skip tests that
# require Unix groups.
testConstraint foundGroup [expr {![testConstraint unix]}]
if {[testConstraint unix]} {
    catch {







<
<
<
<
<
<
<
<
<







22
23
24
25
26
27
28









29
30
31
32
33
34
35
testConstraint winVista 0
testConstraint win2000orXP 0
testConstraint winOlderThan2000 0
# Don't know how to determine this constraint correctly
testConstraint notNetworkFilesystem 0
testConstraint 95or98 [expr {[testConstraint 95] || [testConstraint 98]}]
testConstraint 2000orNewer [expr {![testConstraint 95or98]}]










set tmpspace /tmp;# default value
# Find a group that exists on this Unix system, or else skip tests that
# require Unix groups.
testConstraint foundGroup [expr {![testConstraint unix]}]
if {[testConstraint unix]} {
    catch {
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

    if {[catch {makeDirectory tcl[pid] /tmp} tmpspace] == 0} {
	testConstraint xdev [expr {([dev .] != [dev $tmpspace])}]
    }
}

# Also used in winFCmd...
if {[testConstraint win]} {

    if {[testConstraint nt] && $::tcl_platform(osVersion) >= 5.0} {
        if {$::tcl_platform(osVersion) >= 6.0} {
            testConstraint winVista 1
        } else {
            testConstraint win2000orXP 1
        }
    } else {
        testConstraint winOlderThan2000 1
    }
}

testConstraint darwin9 [expr {
    [testConstraint unix]
    && $tcl_platform(os) eq "Darwin"
    && [package vsatisfies 1.$::tcl_platform(osVersion) 1.9]
}]

testConstraint notDarwin9 [expr {![testConstraint darwin9]}]
testConstraint notContinuousIntegration [expr {![info exists ::env(CI)]}]

testConstraint fileSharing 0
testConstraint notFileSharing 1
testConstraint linkFile 1
testConstraint linkDirectory 1

# Several tests require need to match results against the unix username







|
>
|
|

|







|
<
|
|
<
>

<







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

    if {[catch {makeDirectory tcl[pid] /tmp} tmpspace] == 0} {
	testConstraint xdev [expr {([dev .] != [dev $tmpspace])}]
    }
}

# Also used in winFCmd...
if {[testConstraint winOnly]} {
    set major [string index $tcl_platform(osVersion) 0]
    if {[testConstraint nt] && $major > 4} {
        if {$major > 5} {
            testConstraint winVista 1
        } elseif {$major == 5} {
            testConstraint win2000orXP 1
        }
    } else {
        testConstraint winOlderThan2000 1
    }
}

testConstraint darwin9 [expr {[testConstraint unix] &&

	$tcl_platform(os) eq "Darwin" &&
	int([string range $tcl_platform(osVersion) 0 \

	[string first . $tcl_platform(osVersion)]]) >= 9}]
testConstraint notDarwin9 [expr {![testConstraint darwin9]}]


testConstraint fileSharing 0
testConstraint notFileSharing 1
testConstraint linkFile 1
testConstraint linkDirectory 1

# Several tests require need to match results against the unix username
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    close $f
    return $r
}


set root [lindex [file split [pwd]] 0]

# A really long file name.
# Length of long is 1216 chars, which should be greater than any static buffer
# or allowable filename.

set long "abcdefghihjllmnopqrstuvwxyz01234567890"
append long $long
append long $long
append long $long
append long $long
append long $long

test fCmd-1.1 {TclFileRenameCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}

test fCmd-2.1 {TclFileCopyCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file copy tf1 tf2
    lsort [glob tf*]
} -result {tf1 tf2}

test fCmd-3.1 {FileCopyRename: FileForceOption fails} -constraints {notRoot} -body {
    file rename -xyz
} -returnCodes error -result {bad option "-xyz": should be -force or --}
test fCmd-3.2 {FileCopyRename: not enough args} -constraints {notRoot} -body {
    file rename xyz
} -returnCodes error -result {wrong # args: should be "file rename ?options? source ?source ...? target"}







|
|








|
|

<



|

|

<



|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
    close $f
    return $r
}


set root [lindex [file split [pwd]] 0]

# A really long file name
# length of long is 1216 chars, which should be greater than any static buffer
# or allowable filename.

set long "abcdefghihjllmnopqrstuvwxyz01234567890"
append long $long
append long $long
append long $long
append long $long
append long $long

test fCmd-1.1 {TclFileRenameCmd} {notRoot} {
    cleanup

    createfile tf1
    file rename tf1 tf2
    glob tf*
} {tf2}

test fCmd-2.1 {TclFileCopyCmd} {notRoot} {
    cleanup

    createfile tf1
    file copy tf1 tf2
    lsort [glob tf*]
} {tf1 tf2}

test fCmd-3.1 {FileCopyRename: FileForceOption fails} -constraints {notRoot} -body {
    file rename -xyz
} -returnCodes error -result {bad option "-xyz": should be -force or --}
test fCmd-3.2 {FileCopyRename: not enough args} -constraints {notRoot} -body {
    file rename xyz
} -returnCodes error -result {wrong # args: should be "file rename ?options? source ?source ...? target"}
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
    file rename tf1 tf2 tf3
} -result {error renaming: target "tf3" is not a directory}
test fCmd-3.9 {FileCopyRename: too many arguments: argc - i > 2} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file copy -force -- tf1 tf2 tf3
} -result {error copying: target "tf3" is not a directory}
test fCmd-3.10 {FileCopyRename: just 2 arguments} -constraints notRoot -setup {
    cleanup
} -body {
    createfile tf1 tf1
    file rename tf1 tf2
    contents tf2
} -result {tf1}
test fCmd-3.11 {FileCopyRename: just 2 arguments} -constraints notRoot -setup {
    cleanup
} -body {
    createfile tf1 tf1
    file rename -force -force -- tf1 tf2
    contents tf2
} -result {tf1}
test fCmd-3.12 {FileCopyRename: move each source: 1 source} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1 tf1
    file mkdir td1
    file rename tf1 td1
    contents [file join td1 tf1]
} -result {tf1}
test fCmd-3.13 {FileCopyRename: move each source: multiple sources} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1 tf1
    createfile tf2 tf2
    createfile tf3 tf3
    createfile tf4 tf4
    file mkdir td1
    file rename tf1 tf2 tf3 tf4 td1
    list [contents [file join td1 tf1]] [contents [file join td1 tf2]] \
	[contents [file join td1 tf3]] [contents [file join td1 tf4]]
} -result {tf1 tf2 tf3 tf4}
test fCmd-3.14 {FileCopyRename: FileBasename fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir td1
    file rename ~_totally_bogus_user td1
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-3.15 {FileCopyRename: source[0] == '\0'} -setup {
    cleanup
} -constraints {notRoot unixOrWin} -returnCodes error -body {
    file mkdir td1
    file rename / td1
} -result {error renaming "/" to "td1": file already exists}
test fCmd-3.16 {FileCopyRename: break on first error} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    createfile tf3
    createfile tf4
    file mkdir td1
    createfile [file join td1 tf3]
    file rename tf1 tf2 tf3 tf4 td1
} -result [subst {error renaming "tf3" to "[file join td1 tf3]": file already exists}]

test fCmd-4.1 {TclFileMakeDirsCmd: make each dir: 1 dir} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    glob td*
} -result {td1}
test fCmd-4.2 {TclFileMakeDirsCmd: make each dir: multiple dirs} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1 td2 td3
    lsort [glob td*]
} -result {td1 td2 td3}
test fCmd-4.3 {TclFileMakeDirsCmd: stops on first error} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    catch {file mkdir td1 td2 tf1 td3 td4}
    glob td1 td2 tf1 td3 td4
} -result {td1 td2 tf1}
test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir ~_totally_bogus_user
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir ""
} -result {can't create directory "": no such file or directory}
test fCmd-4.6 {TclFileMakeDirsCmd: one level deep} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    glob td1
} -result {td1}
test fCmd-4.7 {TclFileMakeDirsCmd: multi levels deep} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2 td3 td4]
    glob td1 [file join td1 td2]
} -result "td1 [file join td1 td2]"
test fCmd-4.8 {TclFileMakeDirsCmd: already exist: lstat(target) == 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} -result {1 1}
test fCmd-4.9 {TclFileMakeDirsCmd: exists, not dir} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    file mkdir tf1
} -result [subst {can't create directory "[file join tf1]": file already exists}]
test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} -result {1 1}
test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -returnCodes error -body {
    file mkdir td1/td2/td3
    testchmod 000 td1/td2
    file mkdir td1/td2/td3/td4
} -cleanup {







|

<



|
|

<



|
|

<




|
|

<








|








|















|

<


|
|

<


|
|

<



|










|

<


|
|

<


|
|

<




|






|

<




|







217
218
219
220
221
222
223
224
225

226
227
228
229
230
231

232
233
234
235
236
237

238
239
240
241
242
243
244

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284

285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

306
307
308
309
310

311
312
313
314
315

316
317
318
319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
336
337
338
339
340
    file rename tf1 tf2 tf3
} -result {error renaming: target "tf3" is not a directory}
test fCmd-3.9 {FileCopyRename: too many arguments: argc - i > 2} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file copy -force -- tf1 tf2 tf3
} -result {error copying: target "tf3" is not a directory}
test fCmd-3.10 {FileCopyRename: just 2 arguments} {notRoot} {
    cleanup

    createfile tf1 tf1
    file rename tf1 tf2
    contents tf2
} {tf1}
test fCmd-3.11 {FileCopyRename: just 2 arguments} {notRoot} {
    cleanup

    createfile tf1 tf1
    file rename -force -force -- tf1 tf2
    contents tf2
} {tf1}
test fCmd-3.12 {FileCopyRename: move each source: 1 source} {notRoot} {
    cleanup

    createfile tf1 tf1
    file mkdir td1
    file rename tf1 td1
    contents [file join td1 tf1]
} {tf1}
test fCmd-3.13 {FileCopyRename: move each source: multiple sources} {notRoot} {
    cleanup

    createfile tf1 tf1
    createfile tf2 tf2
    createfile tf3 tf3
    createfile tf4 tf4
    file mkdir td1
    file rename tf1 tf2 tf3 tf4 td1
    list [contents [file join td1 tf1]] [contents [file join td1 tf2]] \
	[contents [file join td1 tf3]] [contents [file join td1 tf4]]
} {tf1 tf2 tf3 tf4}
test fCmd-3.14 {FileCopyRename: FileBasename fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir td1
    file rename ~_totally_bogus_user td1
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-3.15 {FileCopyRename: source[0] == '\0'} -setup {
    cleanup
} -constraints {notRoot unixOrPc} -returnCodes error -body {
    file mkdir td1
    file rename / td1
} -result {error renaming "/" to "td1": file already exists}
test fCmd-3.16 {FileCopyRename: break on first error} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    createfile tf3
    createfile tf4
    file mkdir td1
    createfile [file join td1 tf3]
    file rename tf1 tf2 tf3 tf4 td1
} -result [subst {error renaming "tf3" to "[file join td1 tf3]": file already exists}]

test fCmd-4.1 {TclFileMakeDirsCmd: make each dir: 1 dir} {notRoot} {
    cleanup

    file mkdir td1
    glob td*
} {td1}
test fCmd-4.2 {TclFileMakeDirsCmd: make each dir: multiple dirs} {notRoot} {
    cleanup

    file mkdir td1 td2 td3
    lsort [glob td*]
} {td1 td2 td3}
test fCmd-4.3 {TclFileMakeDirsCmd: stops on first error} {notRoot} {
    cleanup

    createfile tf1
    catch {file mkdir td1 td2 tf1 td3 td4}
    glob td1 td2 tf1 td3 td4
} {td1 td2 tf1}
test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir ~_totally_bogus_user
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir ""
} -result {can't create directory "": no such file or directory}
test fCmd-4.6 {TclFileMakeDirsCmd: one level deep} {notRoot} {
    cleanup

    file mkdir td1
    glob td1
} {td1}
test fCmd-4.7 {TclFileMakeDirsCmd: multi levels deep} {notRoot} {
    cleanup

    file mkdir [file join td1 td2 td3 td4]
    glob td1 [file join td1 td2]
} "td1 [file join td1 td2]"
test fCmd-4.8 {TclFileMakeDirsCmd: already exist: lstat(target) == 0} {notRoot} {
    cleanup

    file mkdir td1
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} {1 1}
test fCmd-4.9 {TclFileMakeDirsCmd: exists, not dir} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    file mkdir tf1
} -result [subst {can't create directory "[file join tf1]": file already exists}]
test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} {notRoot} {
    cleanup

    file mkdir td1
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} {1 1}
test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -returnCodes error -body {
    file mkdir td1/td2/td3
    testchmod 000 td1/td2
    file mkdir td1/td2/td3/td4
} -cleanup {
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
} -constraints {unix notRoot} -body {
    file mkdir foo
    file attr foo -perm 040000
    file mkdir foo/tf1
} -returnCodes error -cleanup {
    file delete -force foo
} -result {can't create directory "foo/tf1": permission denied}
test fCmd-4.16 {TclFileMakeDirsCmd: TclpCreateDirectory succeeds} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir tf1
    file exists tf1
} -result {1}

test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} -constraints {notRoot} -body {
    file delete -xyz
} -returnCodes error -result {bad option "-xyz": should be -force or --}
test fCmd-5.2 {TclFileDeleteCmd: not enough args} -constraints {notRoot} -body {
    file delete -force -force
} -returnCodes error -result {wrong # args: should be "file delete ?options? file ?file ...?"}
test fCmd-5.3 {TclFileDeleteCmd: 1 file} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    file delete tf2
    glob tf* td*
} -result {tf1 td1}
test fCmd-5.4 {TclFileDeleteCmd: multiple files} -constraints notRoot -setup {
    cleanup
} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    set x [list [file exists tf1] [file exists tf2] [file exists td1]]
    file delete tf1 td1 tf2
    lappend x [file exists tf1] [file exists tf2] [file exists tf3]
} -cleanup {cleanup} -result {1 1 1 0 0 0}
test fCmd-5.5 {TclFileDeleteCmd: stop at first error} -setup {
    cleanup
} -constraints {notRoot unixOrWin} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    catch {file delete tf1 td1 $root tf2}
    list [file exists tf1] [file exists tf2] [file exists td1]
} -cleanup {cleanup} -result {0 1 0}
test fCmd-5.6 {TclFileDeleteCmd: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
    file delete ~_totally_bogus_user
} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
test fCmd-5.7 {TclFileDeleteCmd: Tcl_TranslateFileName succeeds} -setup {
    catch {file delete ~/tf1}
} -constraints {notRoot} -body {
    createfile ~/tf1
    file delete ~/tf1
} -result {}
test fCmd-5.8 {TclFileDeleteCmd: file doesn't exist: lstat(name) != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    set x [file exists tf1]
    file delete tf1
    list $x [file exists tf1]
} -result {0 0}
test fCmd-5.9 {TclFileDeleteCmd: is directory} -constraints {notRoot} -setup {
    cleanup
} -body {
    file mkdir td1
    file delete td1
    file exists td1
} -result {0}
test fCmd-5.10 {TclFileDeleteCmd: TclpRemoveDirectory fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir [file join td1 td2]
    file delete td1
} -result {error deleting "td1": directory not empty}
test fCmd-5.11 {TclFileDeleteCmd: TclpRemoveDirectory with cwd inside} -setup {
    cleanup
    set dir [pwd]
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2]
    cd [file join td1 td2]
    set res [list [catch {file delete -force [file dirname [pwd]]} msg]]
    cd $dir
    lappend res [file exists td1] $msg
} -cleanup {
    cd $dir
} -result {0 0 {}}
test fCmd-5.12 {TclFileDeleteCmd: TclpRemoveDirectory with bad perms} -setup {
    cleanup
} -constraints {unix} -body {
    file mkdir [file join td1 td2]

    file attributes [file join td1 td2] -permissions u+rwx
    set res [list [catch {file delete -force td1} msg]]
    lappend res [file exists td1] $msg
} -result {0 0 {}}

test fCmd-6.1 {CopyRenameOneFile: bad source} {notRoot emptyTest} {
    # can't test this, because it's caught by FileCopyRename
} {}
test fCmd-6.2 {CopyRenameOneFile: bad target} {notRoot emptyTest} {
    # can't test this, because it's caught by FileCopyRename
} {}
test fCmd-6.3 {CopyRenameOneFile: lstat(source) != 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file rename tf1 tf2
} -result {error renaming "tf1": no such file or directory}
test fCmd-6.4 {CopyRenameOneFile: lstat(source) == 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.5 {CopyRenameOneFile: lstat(target) != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
    file mkdir td1
    testchmod 000 td1
    createfile tf1
    file rename tf1 td1
} -returnCodes error -cleanup {
    testchmod 755 td1
} -result {error renaming "tf1" to "td1/tf1": permission denied}
test fCmd-6.7 {CopyRenameOneFile: errno != ENOENT} -setup {
    cleanup
} -constraints {win 95} -returnCodes error -body {
    createfile tf1
    file rename tf1 $long
} -result [subst {error renaming "tf1" to "$long": file name too long}]
test fCmd-6.9 {CopyRenameOneFile: errno == ENOENT} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.10 {CopyRenameOneFile: lstat(target) == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
test fCmd-6.11 {CopyRenameOneFile: force == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
test fCmd-6.12 {CopyRenameOneFile: force != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    createfile tf2
    file rename -force tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.13 {CopyRenameOneFile: source is dir, target is file} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir td1
    file mkdir td2
    createfile [file join td2 td1]
    file rename -force td1 td2







|

<


|







|

<





|
|

<






|
|

<





|



|

<


|
|

<



|
|

<



|


















|

<

>



|












|

<



|
|

<



|
















|

<



|














|

<




|







354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402

403
404
405
406
407

408
409
410
411
412
413

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513
514
515
516
517
} -constraints {unix notRoot} -body {
    file mkdir foo
    file attr foo -perm 040000
    file mkdir foo/tf1
} -returnCodes error -cleanup {
    file delete -force foo
} -result {can't create directory "foo/tf1": permission denied}
test fCmd-4.16 {TclFileMakeDirsCmd: TclpCreateDirectory succeeds} {notRoot} {
    cleanup

    file mkdir tf1
    file exists tf1
} {1}

test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} -constraints {notRoot} -body {
    file delete -xyz
} -returnCodes error -result {bad option "-xyz": should be -force or --}
test fCmd-5.2 {TclFileDeleteCmd: not enough args} -constraints {notRoot} -body {
    file delete -force -force
} -returnCodes error -result {wrong # args: should be "file delete ?options? file ?file ...?"}
test fCmd-5.3 {TclFileDeleteCmd: 1 file} {notRoot} {
    cleanup

    createfile tf1
    createfile tf2
    file mkdir td1
    file delete tf2
    glob tf* td*
} {tf1 td1}
test fCmd-5.4 {TclFileDeleteCmd: multiple files} {notRoot} {
    cleanup

    createfile tf1
    createfile tf2
    file mkdir td1
    set x [list [file exists tf1] [file exists tf2] [file exists td1]]
    file delete tf1 td1 tf2
    lappend x [file exists tf1] [file exists tf2] [file exists tf3]
} {1 1 1 0 0 0}
test fCmd-5.5 {TclFileDeleteCmd: stop at first error} {notRoot unixOrPc} {
    cleanup

    createfile tf1
    createfile tf2
    file mkdir td1
    catch {file delete tf1 td1 $root tf2}
    list [file exists tf1] [file exists tf2] [file exists td1]
} {0 1 0}
test fCmd-5.6 {TclFileDeleteCmd: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
    file delete ~_totally_bogus_user
} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
test fCmd-5.7 {TclFileDeleteCmd: Tcl_TranslateFileName succeeds} {notRoot} {
    catch {file delete ~/tf1}

    createfile ~/tf1
    file delete ~/tf1
} {}
test fCmd-5.8 {TclFileDeleteCmd: file doesn't exist: lstat(name) != 0} {notRoot} {
    cleanup

    set x [file exists tf1]
    file delete tf1
    list $x [file exists tf1]
} {0 0}
test fCmd-5.9 {TclFileDeleteCmd: is directory} {notRoot} {
    cleanup

    file mkdir td1
    file delete td1
    file exists td1
} {0}
test fCmd-5.10 {TclFileDeleteCmd: TclpRemoveDirectory fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir [file join td1 td2]
    file delete td1
} -result {error deleting "td1": directory not empty}
test fCmd-5.11 {TclFileDeleteCmd: TclpRemoveDirectory with cwd inside} -setup {
    cleanup
    set dir [pwd]
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2]
    cd [file join td1 td2]
    set res [list [catch {file delete -force [file dirname [pwd]]} msg]]
    cd $dir
    lappend res [file exists td1] $msg
} -cleanup {
    cd $dir
} -result {0 0 {}}
test fCmd-5.12 {TclFileDeleteCmd: TclpRemoveDirectory with bad perms} {unix} {
    cleanup

    file mkdir [file join td1 td2]
    #exec chmod u-rwx [file join td1 td2]
    file attributes [file join td1 td2] -permissions u+rwx
    set res [list [catch {file delete -force td1} msg]]
    lappend res [file exists td1] $msg
} {0 0 {}}

test fCmd-6.1 {CopyRenameOneFile: bad source} {notRoot emptyTest} {
    # can't test this, because it's caught by FileCopyRename
} {}
test fCmd-6.2 {CopyRenameOneFile: bad target} {notRoot emptyTest} {
    # can't test this, because it's caught by FileCopyRename
} {}
test fCmd-6.3 {CopyRenameOneFile: lstat(source) != 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file rename tf1 tf2
} -result {error renaming "tf1": no such file or directory}
test fCmd-6.4 {CopyRenameOneFile: lstat(source) == 0} {notRoot} {
    cleanup

    createfile tf1
    file rename tf1 tf2
    glob tf*
} {tf2}
test fCmd-6.5 {CopyRenameOneFile: lstat(target) != 0} {notRoot} {
    cleanup

    createfile tf1
    file rename tf1 tf2
    glob tf*
} {tf2}
test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
    file mkdir td1
    testchmod 000 td1
    createfile tf1
    file rename tf1 td1
} -returnCodes error -cleanup {
    testchmod 755 td1
} -result {error renaming "tf1" to "td1/tf1": permission denied}
test fCmd-6.7 {CopyRenameOneFile: errno != ENOENT} -setup {
    cleanup
} -constraints {win 95} -returnCodes error -body {
    createfile tf1
    file rename tf1 $long
} -result [subst {error renaming "tf1" to "$long": file name too long}]
test fCmd-6.9 {CopyRenameOneFile: errno == ENOENT} {unix notRoot} {
    cleanup

    createfile tf1
    file rename tf1 tf2
    glob tf*
} {tf2}
test fCmd-6.10 {CopyRenameOneFile: lstat(target) == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
test fCmd-6.11 {CopyRenameOneFile: force == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
test fCmd-6.12 {CopyRenameOneFile: force != 0} {notRoot} {
    cleanup

    createfile tf1
    createfile tf2
    file rename -force tf1 tf2
    glob tf*
} {tf2}
test fCmd-6.13 {CopyRenameOneFile: source is dir, target is file} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir td1
    file mkdir td2
    createfile [file join td2 td1]
    file rename -force td1 td2
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2]
    createfile [file join td1 td2 tf1]
    file mkdir td2
    file rename -force td2 td1
} -returnCodes error -match glob -result \
    [subst {error renaming "td2" to "[file join td1 td2]": file *}]
test fCmd-6.19 {CopyRenameOneFile: errno == EXDEV} -setup {
    cleanup $tmpspace
} -constraints {xdev notRoot} -body {
    createfile tf1
    file rename tf1 $tmpspace
    glob -nocomplain tf* [file join $tmpspace tf1]
} -result [file join $tmpspace tf1]
test fCmd-6.20 {CopyRenameOneFile: errno == EXDEV} -constraints {win} -setup {
    catch {file delete -force c:/tcl8975@ d:/tcl8975@}
} -body {
    file mkdir c:/tcl8975@
    if {[catch {file rename c:/tcl8975@ d:/}]} {
	return d:/tcl8975@
    }
    glob c:/tcl8975@ d:/tcl8975@
} -cleanup {
    file delete -force c:/tcl8975@
    catch {file delete -force d:/tcl8975@}
} -result {d:/tcl8975@}
test fCmd-6.21 {CopyRenameOneFile: copy/rename: S_ISDIR(source)} -setup {

    cleanup $tmpspace
} -constraints {xdev notRoot} -body {
    file mkdir td1
    file rename td1 $tmpspace
    glob -nocomplain td* [file join $tmpspace td*]
} -result [file join $tmpspace td1]
test fCmd-6.22 {CopyRenameOneFile: copy/rename: !S_ISDIR(source)} -setup {

    cleanup $tmpspace
} -constraints {xdev notRoot} -body {
    createfile tf1
    file rename tf1 $tmpspace
    glob -nocomplain tf* [file join $tmpspace tf*]
} -result [file join $tmpspace tf1]
test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {xdev notRoot} -body {
    file mkdir td1/td2/td3
    file attributes td1 -permissions 0000
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1 -permissions 0755
    cleanup
} -match regexp -result {^error renaming "td1"( to "/tmp/tcl\d+/td1")?: permission denied$}







|

<



|












|
>

<



|
|
>

<



|


|







551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2]
    createfile [file join td1 td2 tf1]
    file mkdir td2
    file rename -force td2 td1
} -returnCodes error -match glob -result \
    [subst {error renaming "td2" to "[file join td1 td2]": file *}]
test fCmd-6.19 {CopyRenameOneFile: errno == EXDEV} {xdev notRoot} {
    cleanup $tmpspace

    createfile tf1
    file rename tf1 $tmpspace
    glob -nocomplain tf* [file join $tmpspace tf1]
} [file join $tmpspace tf1]
test fCmd-6.20 {CopyRenameOneFile: errno == EXDEV} -constraints {win} -setup {
    catch {file delete -force c:/tcl8975@ d:/tcl8975@}
} -body {
    file mkdir c:/tcl8975@
    if {[catch {file rename c:/tcl8975@ d:/}]} {
	return d:/tcl8975@
    }
    glob c:/tcl8975@ d:/tcl8975@
} -cleanup {
    file delete -force c:/tcl8975@
    catch {file delete -force d:/tcl8975@}
} -result {d:/tcl8975@}
test fCmd-6.21 {CopyRenameOneFile: copy/rename: S_ISDIR(source)} \
	{xdev notRoot} {
    cleanup $tmpspace

    file mkdir td1
    file rename td1 $tmpspace
    glob -nocomplain td* [file join $tmpspace td*]
} [file join $tmpspace td1]
test fCmd-6.22 {CopyRenameOneFile: copy/rename: !S_ISDIR(source)} \
	{xdev notRoot} {
    cleanup $tmpspace

    createfile tf1
    file rename tf1 $tmpspace
    glob -nocomplain tf* [file join $tmpspace tf*]
} [file join $tmpspace tf1]
test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -body {
    file mkdir td1/td2/td3
    file attributes td1 -permissions 0000
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1 -permissions 0755
    cleanup
} -match regexp -result {^error renaming "td1"( to "/tmp/tcl\d+/td1")?: permission denied$}
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

test fCmd-7.1 {FileForceOption: none} -constraints {notRoot} -setup {
    cleanup
} -returnCodes error -body {
    file mkdir [file join tf1 tf2]
    file delete tf1
} -result {error deleting "tf1": directory not empty}
test fCmd-7.2 {FileForceOption: -force} -constraints {notRoot} -setup {
    cleanup
} -body {
    file mkdir [file join tf1 tf2]
    file delete -force tf1
} -result {}
test fCmd-7.3 {FileForceOption: --} -constraints {notRoot} -body {
    createfile -tf1
    file delete -- -tf1
} -result {}
test fCmd-7.4 {FileForceOption: bad option} -constraints {notRoot} -setup {
    createfile -tf1
} -body {
    file delete -tf1
} -returnCodes error -cleanup {
    file delete -- -tf1
} -result {bad option "-tf1": should be -force or --}







|

<


|
|


|







683
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705

test fCmd-7.1 {FileForceOption: none} -constraints {notRoot} -setup {
    cleanup
} -returnCodes error -body {
    file mkdir [file join tf1 tf2]
    file delete tf1
} -result {error deleting "tf1": directory not empty}
test fCmd-7.2 {FileForceOption: -force} {notRoot} {
    cleanup

    file mkdir [file join tf1 tf2]
    file delete -force tf1
} {}
test fCmd-7.3 {FileForceOption: --} {notRoot} {
    createfile -tf1
    file delete -- -tf1
} {}
test fCmd-7.4 {FileForceOption: bad option} -constraints {notRoot} -setup {
    createfile -tf1
} -body {
    file delete -tf1
} -returnCodes error -cleanup {
    file delete -- -tf1
} -result {bad option "-tf1": should be -force or --}
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
    file mkdir td1
    file attr td1 -perm 040000
    file rename ~$user td1
} -returnCodes error -cleanup {
    file delete -force td1
} -result "error renaming \"~$user\" to \"td1/[file tail ~$user]\": permission denied"
test fCmd-8.2 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
	-constraints {unix notRoot} -body {
    string equal [file tail ~$user] ~$user
} -result 0
test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
    file copy ~ [file join this file doesnt exist]
} -returnCodes error -result [subst \
	{error copying "~" to "[file join this file doesnt exist]": no such file or directory}]

test fCmd-9.1 {file rename: comprehensive: EACCES} -setup {
    cleanup







|

|







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
    file mkdir td1
    file attr td1 -perm 040000
    file rename ~$user td1
} -returnCodes error -cleanup {
    file delete -force td1
} -result "error renaming \"~$user\" to \"td1/[file tail ~$user]\": permission denied"
test fCmd-8.2 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
	{unix notRoot} {
    string equal [file tail ~$user] ~$user
} 0
test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
    file copy ~ [file join this file doesnt exist]
} -returnCodes error -result [subst \
	{error copying "~" to "[file join this file doesnt exist]": no such file or directory}]

test fCmd-9.1 {file rename: comprehensive: EACCES} -setup {
    cleanup
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
    testchmod 444 tf2
    file rename tf1 tf3
    file rename tf2 tf4
    list [lsort [glob tf*]] [file writable tf3] [file writable tf4]
} -result {{tf3 tf4} 1 0}
test fCmd-9.4.a {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {win2000orXP testchmod} -body {
    file mkdir td1 td2
    testchmod 555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.4.b {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {unix notRoot testchmod notDarwin9} -body {
    file mkdir td1 td2
    testchmod 555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.5 {file rename: comprehensive: file to self} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 444 tf2
    file rename -force tf1 tf1
    file rename -force tf2 tf2
    list [contents tf1] [contents tf2] [file writable tf1] [file writable tf2]
} -result {tf1 tf2 1 0}
test fCmd-9.6.a {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {testchmod win2000orXP} -body {
    file mkdir td1
    file mkdir td2
    testchmod 555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}
test fCmd-9.6.b {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
    file mkdir td1
    file mkdir td2
    testchmod 555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}







|



















|

<






|












|







754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
    testchmod 444 tf2
    file rename tf1 tf3
    file rename tf2 tf4
    list [lsort [glob tf*]] [file writable tf3] [file writable tf4]
} -result {{tf3 tf4} 1 0}
test fCmd-9.4.a {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {testchmod win2000orXP} -body {
    file mkdir td1 td2
    testchmod 555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.4.b {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {unix notRoot testchmod notDarwin9} -body {
    file mkdir td1 td2
    testchmod 555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.5 {file rename: comprehensive: file to self} {notRoot testchmod} {
    cleanup

    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 444 tf2
    file rename -force tf1 tf1
    file rename -force tf2 tf2
    list [contents tf1] [contents tf2] [file writable tf1] [file writable tf2]
} {tf1 tf2 1 0}
test fCmd-9.6.a {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {testchmod win2000orXP} -body {
    file mkdir td1
    file mkdir td2
    testchmod 555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}
test fCmd-9.6.b {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {notRoot unix testchmod} -body {
    file mkdir td1
    file mkdir td2
    testchmod 555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}
867
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
    file rename -force tfs3 tfd3
    file rename -force tfs4 tfd4
    list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file already exists}} 1 1 0 0}
test fCmd-9.8 {file rename: comprehensive: dir to empty dir} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    # Under unix, you can rename a read-only directory, but you can't move it
    # into another directory.

    file mkdir td1
    file mkdir [file join td2 td1]
    file mkdir tds1
    file mkdir tds2
    file mkdir tds3
    file mkdir tds4
    file mkdir [file join tdd1 tds1]







|
|
>







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
    file rename -force tfs3 tfd3
    file rename -force tfs4 tfd4
    list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file already exists}} 1 1 0 0}
test fCmd-9.8 {file rename: comprehensive: dir to empty dir} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    # Under unix, you can rename a read-only directory, but you can't
    # move it into another directory.

    file mkdir td1
    file mkdir [file join td2 td1]
    file mkdir tds1
    file mkdir tds2
    file mkdir tds3
    file mkdir tds4
    file mkdir [file join tdd1 tds1]
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
	set w2 0
    } else {
	set w2 [file writable tds2]
    }
    list [lsort [glob td*]] $a1 $a2 [file writable tds1] $w2
} -match glob -result \
    [subst {{tdd1 tdd2 tds1 tds2} {1 {error renaming "tds1" to "[file join tdd1 tds1]": file *}} {1 {error renaming "tds2" to "[file join tdd2 tds2]": file *}} 1 0}]
test fCmd-9.10 {file rename: comprehensive: file to new name and dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    testchmod 444 tf2
    file rename tf1 [file join td1 tf3]
    file rename tf2 [file join td1 tf4]
    list [catch {glob tf*}] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -result [subst {1 {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-9.11 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    file mkdir td1
    file mkdir td2
    file mkdir td3
    if {!([testConstraint unix] || [testConstraint winVista])} {
	testchmod 555 td2
    }
    file rename td1 [file join td3 td3]
    file rename td2 [file join td3 td4]
    if {[testConstraint unix] || [testConstraint winVista]} {
        set w4 0
    } else {
	set w4 [file writable [file join td3 td4]]
    }
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
    [file writable [file join td3 td3]] $w4
} -result [subst {td3 {[file join td3 td3] [file join td3 td4]} 1 0}]
test fCmd-9.12 {file rename: comprehensive: target exists} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    file mkdir [file join td1 td2] [file join td2 td1]
    testchmod 555 [file join td2 td1]
    file mkdir [file join td3 td4] [file join td4 td3]
    file rename -force td3 td4
    list [file exists td3] [file exists [file join td4 td3 td4]] \
	[catch {file rename td1 td2} msg] $msg
} -cleanup {
    testchmod 755 [file join td2 td1]
} -result [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
# Test can hit EEXIST or EBUSY, depending on underlying filesystem
test fCmd-9.13 {file rename: comprehensive: can't overwrite target} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2] [file join td2 td1 td4]
    file rename -force td1 td2
} -returnCodes error -match glob -result \
    [subst {error renaming "td1" to "[file join td2 td1]": file *}]
test fCmd-9.14 {file rename: comprehensive: dir into self} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    list [glob td*] [list [catch {file rename td1 td1} msg] $msg]
} -result [subst {td1 {1 {error renaming "td1" to "[file join td1 td1]": trying to rename a volume or move a directory into itself}}}]
test fCmd-9.14.1 {file rename: comprehensive: dir into self} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    file rename td1 td1x
    file rename td1x td1
    set msg "ok"
} -result {ok}
test fCmd-9.14.2 {file rename: comprehensive: dir into self} -setup {
    cleanup
    set dir [pwd]
} -constraints {nonPortable notRoot} -body {
    file mkdir td1
    cd td1
    file rename [file join .. td1] [file join .. td1x]







|

<








|
|

<















|




















|

<


|
|

<




|







885
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942

943
944
945
946
947

948
949
950
951
952
953
954
955
956
957
958
959
	set w2 0
    } else {
	set w2 [file writable tds2]
    }
    list [lsort [glob td*]] $a1 $a2 [file writable tds1] $w2
} -match glob -result \
    [subst {{tdd1 tdd2 tds1 tds2} {1 {error renaming "tds1" to "[file join tdd1 tds1]": file *}} {1 {error renaming "tds2" to "[file join tdd2 tds2]": file *}} 1 0}]
test fCmd-9.10 {file rename: comprehensive: file to new name and dir} {notRoot testchmod} {
    cleanup

    createfile tf1
    createfile tf2
    file mkdir td1
    testchmod 444 tf2
    file rename tf1 [file join td1 tf3]
    file rename tf2 [file join td1 tf4]
    list [catch {glob tf*}] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} [subst {1 {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-9.11 {file rename: comprehensive: dir to new name and dir} {notRoot testchmod} {
    cleanup

    file mkdir td1
    file mkdir td2
    file mkdir td3
    if {!([testConstraint unix] || [testConstraint winVista])} {
	testchmod 555 td2
    }
    file rename td1 [file join td3 td3]
    file rename td2 [file join td3 td4]
    if {[testConstraint unix] || [testConstraint winVista]} {
        set w4 0
    } else {
	set w4 [file writable [file join td3 td4]]
    }
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
    [file writable [file join td3 td3]] $w4
} [subst {td3 {[file join td3 td3] [file join td3 td4]} 1 0}]
test fCmd-9.12 {file rename: comprehensive: target exists} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    file mkdir [file join td1 td2] [file join td2 td1]
    testchmod 555 [file join td2 td1]
    file mkdir [file join td3 td4] [file join td4 td3]
    file rename -force td3 td4
    list [file exists td3] [file exists [file join td4 td3 td4]] \
	[catch {file rename td1 td2} msg] $msg
} -cleanup {
    testchmod 755 [file join td2 td1]
} -result [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
# Test can hit EEXIST or EBUSY, depending on underlying filesystem
test fCmd-9.13 {file rename: comprehensive: can't overwrite target} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir [file join td1 td2] [file join td2 td1 td4]
    file rename -force td1 td2
} -returnCodes error -match glob -result \
    [subst {error renaming "td1" to "[file join td2 td1]": file *}]
test fCmd-9.14 {file rename: comprehensive: dir into self} {notRoot} {
    cleanup

    file mkdir td1
    list [glob td*] [list [catch {file rename td1 td1} msg] $msg]
} [subst {td1 {1 {error renaming "td1" to "[file join td1 td1]": trying to rename a volume or move a directory into itself}}}]
test fCmd-9.14.1 {file rename: comprehensive: dir into self} {notRoot} {
    cleanup

    file mkdir td1
    file rename td1 td1x
    file rename td1x td1
    set msg "ok"
} {ok}
test fCmd-9.14.2 {file rename: comprehensive: dir into self} -setup {
    cleanup
    set dir [pwd]
} -constraints {nonPortable notRoot} -body {
    file mkdir td1
    cd td1
    file rename [file join .. td1] [file join .. td1x]
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
} -result [subst {can't overwrite directory "[file join td1 tf1]" with file "tf1"}]

test fCmd-10.1 {file copy: comprehensive: source doesn't exist} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file copy tf1 tf2
} -result {error copying "tf1": no such file or directory}
test fCmd-10.2 {file copy: comprehensive: file to new name} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 444 tf2
    file copy tf1 tf3
    file copy tf2 tf4
    list [lsort [glob tf*]] [contents tf3] [contents tf4] [file writable tf3] [file writable tf4]
} -result {{tf1 tf2 tf3 tf4} tf1 tf2 1 0}
test fCmd-10.3 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 555 td2
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \
	    [glob -directory td4 t*] [file writable td3] [file writable td4]
} -cleanup {
    testchmod 755 td2
    testchmod 755 td4
} -result [list {td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 0]
test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {win notRoot 2000orNewer testchmod} -body {
    # On Windows with ACLs, copying a directory is defined like this
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 555 td2
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \







|

<






|


|













|







988
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
} -result [subst {can't overwrite directory "[file join td1 tf1]" with file "tf1"}]

test fCmd-10.1 {file copy: comprehensive: source doesn't exist} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file copy tf1 tf2
} -result {error copying "tf1": no such file or directory}
test fCmd-10.2 {file copy: comprehensive: file to new name} {notRoot testchmod} {
    cleanup

    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 444 tf2
    file copy tf1 tf3
    file copy tf2 tf4
    list [lsort [glob tf*]] [contents tf3] [contents tf4] [file writable tf3] [file writable tf4]
} {{tf1 tf2 tf3 tf4} tf1 tf2 1 0}
test fCmd-10.3 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {notRoot unix testchmod} -body {
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 555 td2
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \
	    [glob -directory td4 t*] [file writable td3] [file writable td4]
} -cleanup {
    testchmod 755 td2
    testchmod 755 td4
} -result [list {td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 0]
test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {notRoot win 2000orNewer testchmod} -body {
    # On Windows with ACLs, copying a directory is defined like this
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 555 td2
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
    set a3 [catch {file copy -force tds2 tdd2}]
    set a4 [catch {file copy -force tds3 tdd3}]
    set a5 [catch {file copy -force tds4 tdd4}]
    list [lsort [glob td*]] $a1 $a2 $a3 $a4 $a5
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
    cleanup
} -constraints {notRoot unixOrWin testchmod} -body {
    file mkdir tds1
    file mkdir tds2
    file mkdir [file join tdd1 tds1 xxx]
    file mkdir [file join tdd2 tds2 xxx]
    testchmod 555 tds2
    set a1 [list [catch {file copy -force tds1 tdd1} msg] $msg]
    set a2 [list [catch {file copy -force tds2 tdd2} msg] $msg]







|







1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
    set a3 [catch {file copy -force tds2 tdd2}]
    set a4 [catch {file copy -force tds3 tdd3}]
    set a5 [catch {file copy -force tds4 tdd4}]
    list [lsort [glob td*]] $a1 $a2 $a3 $a4 $a5
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
    cleanup
} -constraints {notRoot unixOrPc testchmod} -body {
    file mkdir tds1
    file mkdir tds2
    file mkdir [file join tdd1 tds1 xxx]
    file mkdir [file join tdd2 tds2 xxx]
    testchmod 555 tds2
    set a1 [list [catch {file copy -force tds1 tdd1} msg] $msg]
    set a2 [list [catch {file copy -force tds2 tdd2} msg] $msg]
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
    file copy tf1 [file join td1 tf3]
    file copy tf2 [file join td1 tf4]
    list [lsort [glob tf*]] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -result [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
    file mkdir td1
    file mkdir td2
    file mkdir td3
    testchmod 555 td2
    file copy td1 [file join td3 td3]
    file copy td2 [file join td3 td4]
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
    [file writable [file join td3 td3]] [file writable [file join td3 td4]]
} -result [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 0}]
test fCmd-10.8.1 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {win notRoot 2000orNewer testchmod} -body {
    # On Windows with ACLs, copying a directory is defined like this
    file mkdir td1
    file mkdir td2
    file mkdir td3
    testchmod 555 td2
    file copy td1 [file join td3 td3]
    file copy td2 [file join td3 td4]







|











|







1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
    file copy tf1 [file join td1 tf3]
    file copy tf2 [file join td1 tf4]
    list [lsort [glob tf*]] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -result [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {notRoot unix testchmod} -body {
    file mkdir td1
    file mkdir td2
    file mkdir td3
    testchmod 555 td2
    file copy td1 [file join td3 td3]
    file copy td2 [file join td3 td4]
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
    [file writable [file join td3 td3]] [file writable [file join td3 td4]]
} -result [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 0}]
test fCmd-10.8.1 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {notRoot win 2000orNewer testchmod} -body {
    # On Windows with ACLs, copying a directory is defined like this
    file mkdir td1
    file mkdir td2
    file mkdir td3
    testchmod 555 td2
    file copy td1 [file join td3 td3]
    file copy td2 [file join td3 td4]
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
    createfile tf1
    file rename tf1 ""
} -result {error renaming "tf1" to "": no such file or directory}
cleanup

# old tests

test fCmd-11.1 {TclFileRenameCmd: -- option} -constraints notRoot -setup {
    catch {file delete -force -- -tfa1}
} -body {
    set s [createfile -tfa1]
    file rename -- -tfa1 tfa2
    list [checkcontent tfa2 $s] [file exists -tfa1]
} -cleanup {
    file delete tfa2
} -result {1 0}
test fCmd-11.2 {TclFileRenameCmd: bad option} -constraints notRoot -setup {
    catch {file delete -force -- tfa1}
} -body {
    set s [createfile tfa1]
    list [catch {file rename -x tfa1 tfa2}] \
	[checkcontent tfa1 $s] [file exists tfa2]
} -cleanup {
    file delete tfa1
} -result {1 1 0}
test fCmd-11.3 {TclFileRenameCmd: bad \# args} -returnCodes error -body {
    file rename --
} -match glob -result *
test fCmd-11.4 {TclFileRenameCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints notRoot -body {
    global env
    unset env(HOME)
    catch { file rename tfa ~/foobar }
} -cleanup {







|








|








|
|
|







1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
    createfile tf1
    file rename tf1 ""
} -result {error renaming "tf1" to "": no such file or directory}
cleanup

# old tests

test fCmd-11.1 {TclFileRenameCmd: -- option } -constraints notRoot -setup {
    catch {file delete -force -- -tfa1}
} -body {
    set s [createfile -tfa1]
    file rename -- -tfa1 tfa2
    list [checkcontent tfa2 $s] [file exists -tfa1]
} -cleanup {
    file delete tfa2
} -result {1 0}
test fCmd-11.2 {TclFileRenameCmd: bad option } -constraints notRoot -setup {
    catch {file delete -force -- tfa1}
} -body {
    set s [createfile tfa1]
    list [catch {file rename -x tfa1 tfa2}] \
	[checkcontent tfa1 $s] [file exists tfa2]
} -cleanup {
    file delete tfa1
} -result {1 1 0}
test fCmd-11.3 {TclFileRenameCmd: bad \# args} {
    catch {file rename -- }
} {1}
test fCmd-11.4 {TclFileRenameCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints notRoot -body {
    global env
    unset env(HOME)
    catch { file rename tfa ~/foobar }
} -cleanup {
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
} -body {
    set s [createfile tfa1]
    list [catch {file copy -x tfa1 tfa2}] \
	[checkcontent tfa1 $s] [file exists tfa2]
} -cleanup {
    file delete tfa1
} -result {1 1 0}
test fCmd-13.4 {TclCopyFilesCmd: bad \# args} -constraints {notRoot} -body {
    file copy --
} -returnCodes error -match glob -result *
test fCmd-13.5 {TclCopyFilesCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -body {
    global env
    unset env(HOME)
    catch { file copy tfa ~/foobar }
} -cleanup {







|
|
|







1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
} -body {
    set s [createfile tfa1]
    list [catch {file copy -x tfa1 tfa2}] \
	[checkcontent tfa1 $s] [file exists tfa2]
} -cleanup {
    file delete tfa1
} -result {1 1 0}
test fCmd-13.4 {TclCopyFilesCmd: bad \# args} {notRoot} {
    catch {file copy -- }
} {1}
test fCmd-13.5 {TclCopyFilesCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -body {
    global env
    unset env(HOME)
    catch { file copy tfa ~/foobar }
} -cleanup {
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
    list [checkcontent tfad/tfa1 $s] [checkcontent tfa1 $s]
} -cleanup {
    file delete -force tfad tfa1
} -result {1 1}
test fCmd-13.8 {TclCopyFilesCmd: multiple files into directory} -setup {
    catch {file delete -force -- tfa1 tfa2 tfad}
} -constraints {notRoot} -body {
    set s1 [createfile tfa1]
    set s2 [createfile tfa2]
    file mkdir tfad
    file copy tfa1 tfa2 tfad
    list [checkcontent tfad/tfa1 $s1] [checkcontent tfad/tfa2 $s2] \
	[checkcontent tfa1 $s1] [checkcontent tfa2 $s2]
} -cleanup {
    file delete -force tfad tfa1 tfa2
} -result {1 1 1 1}







|
|







1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
    list [checkcontent tfad/tfa1 $s] [checkcontent tfa1 $s]
} -cleanup {
    file delete -force tfad tfa1
} -result {1 1}
test fCmd-13.8 {TclCopyFilesCmd: multiple files into directory} -setup {
    catch {file delete -force -- tfa1 tfa2 tfad}
} -constraints {notRoot} -body {
    set s1 [createfile tfa1 ]
    set s2 [createfile tfa2 ]
    file mkdir tfad
    file copy tfa1 tfa2 tfad
    list [checkcontent tfad/tfa1 $s1] [checkcontent tfad/tfa2 $s2] \
	[checkcontent tfa1 $s1] [checkcontent tfa2 $s2]
} -cleanup {
    file delete -force tfad tfa1 tfa2
} -result {1 1 1 1}
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
    catch {file delete -force -- tfa1 tfa2}
} -constraints notRoot -body {
    list [catch {file copy tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
} -result {1 0 0}
test fCmd-14.4 {copyfile: error copying file to directory} -setup {
    catch {file delete -force -- tfa tfad}
} -constraints {notRoot} -body {
    set s1 [createfile tfa]
    file mkdir tfad
    file mkdir tfad/tfa
    list [catch {file copy tfa tfad}] [checkcontent tfa $s1] \
	[file isdir tfad] [file isdir tfad/tfa]
} -cleanup {
    file delete -force tfa tfad
} -result {1 1 1 1}







|







1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
    catch {file delete -force -- tfa1 tfa2}
} -constraints notRoot -body {
    list [catch {file copy tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
} -result {1 0 0}
test fCmd-14.4 {copyfile: error copying file to directory} -setup {
    catch {file delete -force -- tfa tfad}
} -constraints {notRoot} -body {
    set s1 [createfile tfa ]
    file mkdir tfad
    file mkdir tfad/tfa
    list [catch {file copy tfa tfad}] [checkcontent tfa $s1] \
	[file isdir tfad] [file isdir tfad/tfa]
} -cleanup {
    file delete -force tfa tfad
} -result {1 1 1 1}
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1562
1563
    global env
    unset env(HOME)
    catch {file mkdir ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
#
# Can Tcl_SplitPath return argc == 0? If so them we need a test for that code.

#
test fCmd-15.2 {TclMakeDirsCmd - one directory} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa
    file isdirectory tfa
} -cleanup {
    file delete tfa
} -result {1}







|
>

|







1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
    global env
    unset env(HOME)
    catch {file mkdir ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
#
# Can Tcl_SplitPath return argc == 0? If so them we need a
# test for that code.
#
test fCmd-15.2 {TclMakeDirsCmd - one directory } -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa
    file isdirectory tfa
} -cleanup {
    file delete tfa
} -result {1}
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
} -cleanup {
    file delete $f [file join [pwd] tfa]
} -result {1}

#
# Functionality tests for TclFileRenameCmd()
#

test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
	-setup {
    catch {file delete -force -- tfad}
    set savedDir [pwd]
} -constraints {notRoot} -body {
    file mkdir tfad/dir
    cd tfad/dir
    set s [createfile foo]
    file rename  foo bar
    file rename bar ./foo
    file rename ./foo bar
    file rename ./bar ./foo
    file rename foo ../dir/bar
    file rename ../dir/bar ./foo
    file rename ../../tfad/dir/foo ../../tfad/dir/bar







>







|







1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
} -cleanup {
    file delete $f [file join [pwd] tfa]
} -result {1}

#
# Functionality tests for TclFileRenameCmd()
#

test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
	-setup {
    catch {file delete -force -- tfad}
    set savedDir [pwd]
} -constraints {notRoot} -body {
    file mkdir tfad/dir
    cd tfad/dir
    set s [createfile foo ]
    file rename  foo bar
    file rename bar ./foo
    file rename ./foo bar
    file rename ./bar ./foo
    file rename foo ../dir/bar
    file rename ../dir/bar ./foo
    file rename ../../tfad/dir/foo ../../tfad/dir/bar
1879
1880
1881
1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
} -result {1 0}
test fCmd-18.15 {TclFileRenameCmd : rename a file to a symlink dir} -setup {
    catch {file delete -force -- tfa1 tfa2 tfalink}
} -constraints {unix notRoot} -body {
    file mkdir tfa1
    set s [createfile tfa2]
    file link -symbolic tfalink tfa1

    file rename tfa2 tfalink
    checkcontent tfa1/tfa2 $s
} -cleanup {
    file delete -force tfa1 tfalink
} -result {1}
test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} -setup {
    catch {file delete -force -- tfa1 tfalink}







>







1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
} -result {1 0}
test fCmd-18.15 {TclFileRenameCmd : rename a file to a symlink dir} -setup {
    catch {file delete -force -- tfa1 tfa2 tfalink}
} -constraints {unix notRoot} -body {
    file mkdir tfa1
    set s [createfile tfa2]
    file link -symbolic tfalink tfa1

    file rename tfa2 tfalink
    checkcontent tfa1/tfa2 $s
} -cleanup {
    file delete -force tfa1 tfalink
} -result {1}
test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} -setup {
    catch {file delete -force -- tfa1 tfalink}
1930
1931
1932
1933
1934
1935
1936

1937
1938
1939
1940

1941
1942
1943
1944
1945
1946
1947
    file exists tfa
} -result {0}

#
# TclUnixDeleteFile and TraversalDelete are covered by tests from the
# TclDeleteFilesCmd suite
#


#
# Coverage tests for TraverseUnixTree(), called from TclDeleteFilesCmd
#

test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory } -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa/a -permissions 0000
    catch {file delete -force tfa}







>




>







1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
    file exists tfa
} -result {0}

#
# TclUnixDeleteFile and TraversalDelete are covered by tests from the
# TclDeleteFilesCmd suite
#
#

#
# Coverage tests for TraverseUnixTree(), called from TclDeleteFilesCmd
#

test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory } -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa/a -permissions 0000
    catch {file delete -force tfa}
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
# Coverage testing for TclpRenameFile
#
test fCmd-22.1 {TclpRenameFile: rename and overwrite in a single dir} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    set s2 [createfile tfa2 q]

    set result [catch {file rename tfa1 tfa2}]
    file rename -force tfa1 tfa2
    lappend result [checkcontent tfa2 $s]
} -cleanup {
    file delete [glob tfa1 tfa2]
} -result {1 1}
test fCmd-22.2 {TclpRenameFile: attempt to overwrite itself} -setup {







>







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
# Coverage testing for TclpRenameFile
#
test fCmd-22.1 {TclpRenameFile: rename and overwrite in a single dir} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    set s2 [createfile tfa2 q]

    set result [catch {file rename tfa1 tfa2}]
    file rename -force tfa1 tfa2
    lappend result [checkcontent tfa2 $s]
} -cleanup {
    file delete [glob tfa1 tfa2]
} -result {1 1}
test fCmd-22.2 {TclpRenameFile: attempt to overwrite itself} -setup {
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171

2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
# TclMacCopyFile needs to be redone.
#
test fCmd-22.5 {TclMacCopyFile: copy and overwrite in a single dir} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    set s2 [createfile tfa2 q]

    set result [catch {file copy tfa1 tfa2}]
    file copy -force tfa1 tfa2
    lappend result [checkcontent tfa2 $s] [checkcontent tfa1 $s]
} -cleanup {
    file delete tfa1 tfa2
} -result {1 1 1}

#
# TclMacMkdir - basic cases are covered elsewhere.
# Error cases are not covered.
#

#
# TclMacRmdir
# Error cases are not covered.
#

test fCmd-23.1 {TclMacRmdir: trying to remove a nonempty directory} -setup {
    catch {file delete -force -- tfad}
} -constraints {notRoot} -body {
    file mkdir [file join tfad dir]

    list [catch {file delete tfad}] [file delete -force tfad]
} -cleanup {
    catch {file delete -force tfad}
} -result {1 {}}

#
# TclMacDeleteFile







>
















>




>







2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
# TclMacCopyFile needs to be redone.
#
test fCmd-22.5 {TclMacCopyFile: copy and overwrite in a single dir} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    set s2 [createfile tfa2 q]

    set result [catch {file copy tfa1 tfa2}]
    file copy -force tfa1 tfa2
    lappend result [checkcontent tfa2 $s] [checkcontent tfa1 $s]
} -cleanup {
    file delete tfa1 tfa2
} -result {1 1 1}

#
# TclMacMkdir - basic cases are covered elsewhere.
# Error cases are not covered.
#

#
# TclMacRmdir
# Error cases are not covered.
#

test fCmd-23.1 {TclMacRmdir: trying to remove a nonempty directory} -setup {
    catch {file delete -force -- tfad}
} -constraints {notRoot} -body {
    file mkdir [file join tfad dir]

    list [catch {file delete tfad}] [file delete -force tfad]
} -cleanup {
    catch {file delete -force tfad}
} -result {1 {}}

#
# TclMacDeleteFile
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261

2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
} -cleanup {
    file delete -force tfad1 tfad2
} -result {1 1}

#
# Functionality tests for TclDeleteFilesCmd
#

test fCmd-26.1 {TclDeleteFilesCmd: delete symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file link -symbolic tfalink tfad1
    file delete tfalink

    list [file isdir tfad1] [file exists tfalink]
} -cleanup {
    file delete tfad1
    catch {file delete tfalink}
} -result {1 0}
test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file mkdir tfad2
    file link -symbolic [file join tfad2 link] [file join .. tfad1]
    file delete -force tfad2

    list [file isdir tfad1] [file exists tfad2]
} -cleanup {
    file delete tfad1
} -result {1 0}
test fCmd-26.3 {TclDeleteFilesCmd: delete dangling symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file link -symbolic tfad2 tfad1
    file delete tfad1
    file delete tfad2

    list [file exists tfad1] [file exists tfad2]
} -result {0 0}

# There is no fCmd-27.1
test fCmd-27.2 {TclFileAttrsCmd - Tcl_TranslateFileName fails} -setup {
    set platform [testgetplatform]
} -constraints {testsetplatform} -body {
    testsetplatform unix
    file attributes ~_totally_bogus_user
} -returnCodes error -cleanup {
    testsetplatform $platform







>






>












>











>



<







2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236

2237
2238
2239
2240
2241
2242
2243
} -cleanup {
    file delete -force tfad1 tfad2
} -result {1 1}

#
# Functionality tests for TclDeleteFilesCmd
#

test fCmd-26.1 {TclDeleteFilesCmd: delete symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file link -symbolic tfalink tfad1
    file delete tfalink

    list [file isdir tfad1] [file exists tfalink]
} -cleanup {
    file delete tfad1
    catch {file delete tfalink}
} -result {1 0}
test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file mkdir tfad2
    file link -symbolic [file join tfad2 link] [file join .. tfad1]
    file delete -force tfad2

    list [file isdir tfad1] [file exists tfad2]
} -cleanup {
    file delete tfad1
} -result {1 0}
test fCmd-26.3 {TclDeleteFilesCmd: delete dangling symlink} -setup {
    catch {file delete -force -- tfad1 tfad2}
} -constraints {unix notRoot} -body {
    file mkdir tfad1
    file link -symbolic tfad2 tfad1
    file delete tfad1
    file delete tfad2

    list [file exists tfad1] [file exists tfad2]
} -result {0 0}


test fCmd-27.2 {TclFileAttrsCmd - Tcl_TranslateFileName fails} -setup {
    set platform [testgetplatform]
} -constraints {testsetplatform} -body {
    testsetplatform unix
    file attributes ~_totally_bogus_user
} -returnCodes error -cleanup {
    testsetplatform $platform
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
    file attributes foo.tmp {*}[lrange $attrs 0 3]
} -cleanup {
    file delete -force -- foo.tmp
} -result {}

if {
    [testConstraint win] &&
    ($::tcl_platform(osVersion) < 5.0
     || [lindex [file system [temporaryDirectory]] 1] ne "NTFS")
} then {
    testConstraint linkDirectory 0
    testConstraint linkFile 0
}

test fCmd-28.1 {file link} -returnCodes error -body {







|







2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
    file attributes foo.tmp {*}[lrange $attrs 0 3]
} -cleanup {
    file delete -force -- foo.tmp
} -result {}

if {
    [testConstraint win] &&
    ([string index $tcl_platform(osVersion) 0] < 5
     || [lindex [file system [temporaryDirectory]] 1] ne "NTFS")
} then {
    testConstraint linkDirectory 0
    testConstraint linkFile 0
}

test fCmd-28.1 {file link} -returnCodes error -body {
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
    file link abc.link abc.dir
    set orig [pwd]
    cd abc.link
    set dir [pwd]
    cd ..
    set up [pwd]
    cd $orig
    # Now '$up' should be either $orig or [file dirname abc.dir], depending on
    # whether 'cd' actually moves to the destination of a link, or simply
    # treats the link as a directory. (On windows the former, on unix the
    # latter, I believe)
    if {
	([file normalize $up] ne [file normalize $orig]) &&
	([file normalize $up] ne [file normalize [file dirname abc.dir]])
    } then {







|







2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
    file link abc.link abc.dir
    set orig [pwd]
    cd abc.link
    set dir [pwd]
    cd ..
    set up [pwd]
    cd $orig
    # now '$up' should be either $orig or [file dirname abc.dir], depending on
    # whether 'cd' actually moves to the destination of a link, or simply
    # treats the link as a directory. (On windows the former, on unix the
    # latter, I believe)
    if {
	([file normalize $up] ne [file normalize $orig]) &&
	([file normalize $up] ne [file normalize [file dirname abc.dir]])
    } then {
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
file delete -force d1/d2
file delete -force d1
cd [workingDirectory]

test fCmd-30.1 {file writable on 'My Documents'} -setup {
    # Get the localized version of the folder name by looking in the registry.
    set mydocsname [registry get {HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders} Personal]
} -constraints {win reg nonPortable} -body {
    file writable $mydocsname
} -result 1
test fCmd-30.2 {file readable on 'NTUSER.DAT'} -constraints {win} -body {
    expr {[info exists env(USERPROFILE)]
          && [file exists $env(USERPROFILE)/NTUSER.DAT]
          && [file readable $env(USERPROFILE)/NTUSER.DAT]}
} -result {1}
# At least one CI environment (GitHub Actions) is set up with the page file in
# an unusual location; skip the test if that is so.
test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {
    win notContinuousIntegration
} -body {
    set r {}
    if {[info exists env(SystemDrive)]} {
        set path $env(SystemDrive)/pagefile.sys
        lappend r exists [file exists $path]
        lappend r readable [file readable $path]
        lappend r stat [catch {file stat $path a} e] $e
    }







|







<
<
|
<
<







2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552


2553


2554
2555
2556
2557
2558
2559
2560
file delete -force d1/d2
file delete -force d1
cd [workingDirectory]

test fCmd-30.1 {file writable on 'My Documents'} -setup {
    # Get the localized version of the folder name by looking in the registry.
    set mydocsname [registry get {HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders} Personal]
} -constraints {win reg} -body {
    file writable $mydocsname
} -result 1
test fCmd-30.2 {file readable on 'NTUSER.DAT'} -constraints {win} -body {
    expr {[info exists env(USERPROFILE)]
          && [file exists $env(USERPROFILE)/NTUSER.DAT]
          && [file readable $env(USERPROFILE)/NTUSER.DAT]}
} -result {1}


test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win} -body {


    set r {}
    if {[info exists env(SystemDrive)]} {
        set path $env(SystemDrive)/pagefile.sys
        lappend r exists [file exists $path]
        lappend r readable [file readable $path]
        lappend r stat [catch {file stat $path a} e] $e
    }

Changes to tests/fileName.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
}

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
testConstraint linkDirectory 1
testConstraint symbolicLinkFile 1
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) < 5.0 \
	    || [lindex [file system [temporaryDirectory]] 1] ne "NTFS"} {
	testConstraint linkDirectory 0
    }
    testConstraint symbolicLinkFile 0
    testConstraint sharedCdrive [expr {![catch {cd //[info hostname]/c}]}]
}

global env
if {[testConstraint testsetplatform]} {
    set platform [testgetplatform]
}








|




<







16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
}

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
testConstraint linkDirectory 1
testConstraint symbolicLinkFile 1
if {[testConstraint win]} {
    if {[string index $tcl_platform(osVersion) 0] < 5 \
	    || [lindex [file system [temporaryDirectory]] 1] ne "NTFS"} {
	testConstraint linkDirectory 0
    }
    testConstraint symbolicLinkFile 0

}

global env
if {[testConstraint testsetplatform]} {
    set platform [testgetplatform]
}

207
208
209
210
211
212
213

214
215
216

217
218
219
220
221
222
223
    testsetplatform unix
    file split ~foo/~bar/~baz
} {~foo ./~bar ./~baz}
test filename-4.18 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split foo/bar~/baz
} {foo bar~ baz}

if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}

test filename-4.19 {Tcl_SplitPath} {
    set oldDir [pwd]
    set res [catch {
	cd [temporaryDirectory]
	file mkdir tildetmp
	set nastydir [file join tildetmp ./~tilde]
	file mkdir $nastydir







>



>







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    testsetplatform unix
    file split ~foo/~bar/~baz
} {~foo ./~bar ./~baz}
test filename-4.18 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split foo/bar~/baz
} {foo bar~ baz}

if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}

test filename-4.19 {Tcl_SplitPath} {
    set oldDir [pwd]
    set res [catch {
	cd [temporaryDirectory]
	file mkdir tildetmp
	set nastydir [file join tildetmp ./~tilde]
	file mkdir $nastydir
432
433
434
435
436
437
438

439
440
441
442
443
444
445
test filename-7.18 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join /// a b
} "/a/b"
test filename-7.19 {[Bug f34cf83dd0]} {
    file join foo //bar
} /bar


test filename-9.1 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join a b
} {a/b}
test filename-9.2 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win







>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
test filename-7.18 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join /// a b
} "/a/b"
test filename-7.19 {[Bug f34cf83dd0]} {
    file join foo //bar
} /bar


test filename-9.1 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join a b
} {a/b}
test filename-9.2 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    testsetplatform win
    file join foo/./bar
} {foo/./bar}
test filename-9.19 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
	[file join {C:\foo\bar}] \
	[file join C:/blah {C:\foo\bar}] \
	[file join C:/blah C:/blah {C:\foo\bar}]
} {C:/foo/bar C:/foo/bar C:/foo/bar}
test filename-9.19.1 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
	[file join {foo\bar}] \
	[file join C:/blah {foo\bar}] \
	[file join C:/blah C:/blah {foo\bar}]
} {foo/bar C:/blah/foo/bar C:/blah/foo/bar}
test filename-9.19.2 {Tcl_JoinPath: win} {testsetplatform win} {
    testsetplatform win
    set res {}
    lappend res \
	[file join {foo\bar}] \
	[file join [pwd] {foo\bar}] \
	[file join [pwd] [pwd] {foo\bar}]
    set nres {}
    foreach elt $res {
	lappend nres [string map [list [pwd] pwd] $elt]
    }
    set nres
} {foo/bar pwd/foo/bar pwd/foo/bar}
test filename-9.20 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    set res {}
    lappend res \
	[file join {/foo/bar}] \
	[file join /x {/foo/bar}] \
	[file join /x /x {/foo/bar}]
} {/foo/bar /foo/bar /foo/bar}
test filename-9.23 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
	[file join {foo\bar}] \
	[file join C:/blah {foo\bar}] \
	[file join C:/blah C:/blah {foo\bar}]
    string map [list C:/blah ""] $res
} {foo/bar /foo/bar /foo/bar}
test filename-9.24 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    set res {}
    lappend res \
	[file join {foo/bar}] \
	[file join /x {foo/bar}] \
	[file join /x /x {foo/bar}]
    string map [list /x ""] $res
} {foo/bar /foo/bar /foo/bar}

test filename-10.1 {Tcl_TranslateFileName} {testsetplatform} {
    testsetplatform unix
    list [catch {testtranslatefilename foo} msg] $msg
} {0 foo}







|
|
|





|
|
|





|
|
|










|
|
|





|
|
|






|
|
|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
    testsetplatform win
    file join foo/./bar
} {foo/./bar}
test filename-9.19 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
      [file join {C:\foo\bar}] \
      [file join C:/blah {C:\foo\bar}] \
      [file join C:/blah C:/blah {C:\foo\bar}]
} {C:/foo/bar C:/foo/bar C:/foo/bar}
test filename-9.19.1 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
      [file join {foo\bar}] \
      [file join C:/blah {foo\bar}] \
      [file join C:/blah C:/blah {foo\bar}]
} {foo/bar C:/blah/foo/bar C:/blah/foo/bar}
test filename-9.19.2 {Tcl_JoinPath: win} {testsetplatform win} {
    testsetplatform win
    set res {}
    lappend res \
      [file join {foo\bar}] \
      [file join [pwd] {foo\bar}] \
      [file join [pwd] [pwd] {foo\bar}]
    set nres {}
    foreach elt $res {
	lappend nres [string map [list [pwd] pwd] $elt]
    }
    set nres
} {foo/bar pwd/foo/bar pwd/foo/bar}
test filename-9.20 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    set res {}
    lappend res \
      [file join {/foo/bar}] \
      [file join /x {/foo/bar}] \
      [file join /x /x {/foo/bar}]
} {/foo/bar /foo/bar /foo/bar}
test filename-9.23 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    set res {}
    lappend res \
      [file join {foo\bar}] \
      [file join C:/blah {foo\bar}] \
      [file join C:/blah C:/blah {foo\bar}]
    string map [list C:/blah ""] $res
} {foo/bar /foo/bar /foo/bar}
test filename-9.24 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    set res {}
    lappend res \
      [file join {foo/bar}] \
      [file join /x {foo/bar}] \
      [file join /x /x {foo/bar}]
    string map [list /x ""] $res
} {foo/bar /foo/bar /foo/bar}

test filename-10.1 {Tcl_TranslateFileName} {testsetplatform} {
    testsetplatform unix
    list [catch {testtranslatefilename foo} msg] $msg
} {0 foo}
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
} {1 {bad argument to "-types": abcde}}
test filename-11.48 {Tcl_GlobCmd} {
    list [catch {glob -types abcde -dir foo -join * *} msg] $msg
} {1 {bad argument to "-types": abcde}}
test filename-11.49 {Tcl_GlobCmd} {
    list [catch {glob -types abcde -path foo -join * *} msg] $msg
} {1 {bad argument to "-types": abcde}}
test filename-11.50 {Tcl_GlobCmd} -returnCodes error -body {
    glob -path hello -path salut *
} -result {"-path" may only be used once}
test filename-11.51 {Tcl_GlobCmd} -returnCodes error -body {
    glob -dir hello -dir salut *
} -result {"-directory" may only be used once}

file rename $horribleglobname globTest
file delete -force $tildeglobname
set globname globTest
unset horribleglobname tildeglobname

test filename-12.1 {simple globbing} {unixOrWin} {
    list [catch {glob {}} msg] $msg
} {0 .}
test filename-12.1.1 {simple globbing} {unixOrWin} {
    list [catch {glob -types f {}} msg] $msg
} {1 {no files matched glob pattern ""}}
test filename-12.1.2 {simple globbing} {unixOrWin} {
    list [catch {glob -types d {}} msg] $msg
} {0 .}
test filename-12.1.3 {simple globbing} {unix} {
    list [catch {glob -types hidden {}} msg] $msg
} {0 .}
test filename-12.1.4 {simple globbing} {win} {
    list [catch {glob -types hidden {}} msg] $msg







<
<
<
<
<
<






|


|


|







1106
1107
1108
1109
1110
1111
1112






1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
} {1 {bad argument to "-types": abcde}}
test filename-11.48 {Tcl_GlobCmd} {
    list [catch {glob -types abcde -dir foo -join * *} msg] $msg
} {1 {bad argument to "-types": abcde}}
test filename-11.49 {Tcl_GlobCmd} {
    list [catch {glob -types abcde -path foo -join * *} msg] $msg
} {1 {bad argument to "-types": abcde}}







file rename $horribleglobname globTest
file delete -force $tildeglobname
set globname globTest
unset horribleglobname tildeglobname

test filename-12.1 {simple globbing} {unixOrPc} {
    list [catch {glob {}} msg] $msg
} {0 .}
test filename-12.1.1 {simple globbing} {unixOrPc} {
    list [catch {glob -types f {}} msg] $msg
} {1 {no files matched glob pattern ""}}
test filename-12.1.2 {simple globbing} {unixOrPc} {
    list [catch {glob -types d {}} msg] $msg
} {0 .}
test filename-12.1.3 {simple globbing} {unix} {
    list [catch {glob -types hidden {}} msg] $msg
} {0 .}
test filename-12.1.4 {simple globbing} {win} {
    list [catch {glob -types hidden {}} msg] $msg
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
test filename-12.3 {simple globbing} {
    list [catch {glob -nocomplain \{a1,a2\}} msg] $msg
} {0 {}}

set globPreResult globTest/
set x1 x1.c
set y1 y1.c
test filename-12.4 {simple globbing} {unixOrWin} {
    lsort [glob globTest/x1.c globTest/y1.c globTest/foo]
} "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} {
    list [catch {glob globTest\\/x1.c} msg] $msg
} "0 $globPreResult$x1"
test filename-12.6 {simple globbing} {
    list [catch {glob globTest\\/\\x1.c} msg] $msg







|







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
test filename-12.3 {simple globbing} {
    list [catch {glob -nocomplain \{a1,a2\}} msg] $msg
} {0 {}}

set globPreResult globTest/
set x1 x1.c
set y1 y1.c
test filename-12.4 {simple globbing} {unixOrPc} {
    lsort [glob globTest/x1.c globTest/y1.c globTest/foo]
} "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} {
    list [catch {glob globTest\\/x1.c} msg] $msg
} "0 $globPreResult$x1"
test filename-12.6 {simple globbing} {
    list [catch {glob globTest\\/\\x1.c} msg] $msg
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
} "0 $globPreResult$x1"
test filename-13.9 {globbing with brace substitution} {
    list [lsort [catch {glob globTest/\{x,y\}1.c} msg]] $msg
} [list 0 [list $globPreResult$x1 $globPreResult$y1]]
test filename-13.10 {globbing with brace substitution} {
    list [lsort [catch {glob globTest/\{x,,y\}1.c} msg]] $msg
} [list 0 [list $globPreResult$x1 $globPreResult$y1]]
test filename-13.11 {globbing with brace substitution} {unixOrWin} {
    list [lsort [catch {glob globTest/\{x,x\\,z,z\}1.c} msg]] $msg
} {0 {globTest/x1.c globTest/x,z1.c globTest/z1.c}}
test filename-13.13 {globbing with brace substitution} {
    lsort [glob globTest/{a,b,x,y}1.c]
} [list $globPreResult$x1 $globPreResult$y1]
test filename-13.14 {globbing with brace substitution} {unixOrWin} {
    lsort [glob {globTest/{x1,y2,weird name}.c}]
} {{globTest/weird name.c} globTest/x1.c}
test filename-13.16 {globbing with brace substitution} {unixOrWin} {
    lsort [glob globTest/{x1.c,a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
test filename-13.18 {globbing with brace substitution} {unixOrWin} {
    lsort [glob globTest/{x1.c,{a},a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
test filename-13.20 {globbing with brace substitution} {unixOrWin} {
    lsort [glob globTest/{a,x}1/*/{x,y}*]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}
test filename-13.22 {globbing with brace substitution} {
    list [catch {glob globTest/\{a,x\}1/*/\{} msg] $msg
} {1 {unmatched open-brace in file name}}

test filename-14.1 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob glo*/*.c]
} {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.3 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob globTest/?1.c]
} {globTest/x1.c globTest/y1.c globTest/z1.c}

# The current directory could be anywhere; do this to stop spurious matches
file mkdir globTestContext
file rename globTest [file join globTestContext globTest]
set savepwd [pwd]
cd globTestContext

test filename-14.5 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob */*/*/*.c]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}

# Reset to where we were
cd $savepwd
file rename [file join globTestContext globTest] globTest
file delete globTestContext

test filename-14.7 {asterisks, question marks, and brackets} {unix} {
    lsort [glob globTest/*]
} {globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.7.1 {asterisks, question marks, and brackets} {win} {
    lsort [glob globTest/*]
} {globTest/.1 globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.9 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob globTest/.*]
} {globTest/. globTest/.. globTest/.1}
test filename-14.11 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob globTest/*/*]
} {globTest/a1/b1 globTest/a1/b2 globTest/a2/b3}
test filename-14.13 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob {globTest/[xyab]1.*}]
} {globTest/x1.c globTest/y1.c}
test filename-14.15 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob globTest/*/]
} {globTest/a1/ globTest/a2/ globTest/a3/}
test filename-14.17 {asterisks, question marks, and brackets} {
    global env
    set temp $env(HOME)
    set env(HOME) [file join $env(HOME) globTest]
    set result [list [catch {glob ~/z*} msg] $msg]
    set env(HOME) $temp
    set result
} [list 0 [list [file join $env(HOME) globTest z1.c]]]
test filename-14.18 {asterisks, question marks, and brackets} {unixOrWin} {
    list [catch {lsort [glob globTest/*.c goo/*]} msg] $msg
} {0 {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}}
test filename-14.20 {asterisks, question marks, and brackets} {
    list [catch {glob -nocomplain goo/*} msg] $msg
} {0 {}}
test filename-14.21 {asterisks, question marks, and brackets} {
    list [catch {glob globTest/*/gorp} msg] $msg







|





|


|


|


|






|


|









|














|


|


|


|










|







1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
} "0 $globPreResult$x1"
test filename-13.9 {globbing with brace substitution} {
    list [lsort [catch {glob globTest/\{x,y\}1.c} msg]] $msg
} [list 0 [list $globPreResult$x1 $globPreResult$y1]]
test filename-13.10 {globbing with brace substitution} {
    list [lsort [catch {glob globTest/\{x,,y\}1.c} msg]] $msg
} [list 0 [list $globPreResult$x1 $globPreResult$y1]]
test filename-13.11 {globbing with brace substitution} {unixOrPc} {
    list [lsort [catch {glob globTest/\{x,x\\,z,z\}1.c} msg]] $msg
} {0 {globTest/x1.c globTest/x,z1.c globTest/z1.c}}
test filename-13.13 {globbing with brace substitution} {
    lsort [glob globTest/{a,b,x,y}1.c]
} [list $globPreResult$x1 $globPreResult$y1]
test filename-13.14 {globbing with brace substitution} {unixOrPc} {
    lsort [glob {globTest/{x1,y2,weird name}.c}]
} {{globTest/weird name.c} globTest/x1.c}
test filename-13.16 {globbing with brace substitution} {unixOrPc} {
    lsort [glob globTest/{x1.c,a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
test filename-13.18 {globbing with brace substitution} {unixOrPc} {
    lsort [glob globTest/{x1.c,{a},a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
test filename-13.20 {globbing with brace substitution} {unixOrPc} {
    lsort [glob globTest/{a,x}1/*/{x,y}*]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}
test filename-13.22 {globbing with brace substitution} {
    list [catch {glob globTest/\{a,x\}1/*/\{} msg] $msg
} {1 {unmatched open-brace in file name}}

test filename-14.1 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob glo*/*.c]
} {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.3 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob globTest/?1.c]
} {globTest/x1.c globTest/y1.c globTest/z1.c}

# The current directory could be anywhere; do this to stop spurious matches
file mkdir globTestContext
file rename globTest [file join globTestContext globTest]
set savepwd [pwd]
cd globTestContext

test filename-14.5 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob */*/*/*.c]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}

# Reset to where we were
cd $savepwd
file rename [file join globTestContext globTest] globTest
file delete globTestContext

test filename-14.7 {asterisks, question marks, and brackets} {unix} {
    lsort [glob globTest/*]
} {globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.7.1 {asterisks, question marks, and brackets} {win} {
    lsort [glob globTest/*]
} {globTest/.1 globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.9 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob globTest/.*]
} {globTest/. globTest/.. globTest/.1}
test filename-14.11 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob globTest/*/*]
} {globTest/a1/b1 globTest/a1/b2 globTest/a2/b3}
test filename-14.13 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob {globTest/[xyab]1.*}]
} {globTest/x1.c globTest/y1.c}
test filename-14.15 {asterisks, question marks, and brackets} {unixOrPc} {
    lsort [glob globTest/*/]
} {globTest/a1/ globTest/a2/ globTest/a3/}
test filename-14.17 {asterisks, question marks, and brackets} {
    global env
    set temp $env(HOME)
    set env(HOME) [file join $env(HOME) globTest]
    set result [list [catch {glob ~/z*} msg] $msg]
    set env(HOME) $temp
    set result
} [list 0 [list [file join $env(HOME) globTest z1.c]]]
test filename-14.18 {asterisks, question marks, and brackets} {unixOrPc} {
    list [catch {lsort [glob globTest/*.c goo/*]} msg] $msg
} {0 {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}}
test filename-14.20 {asterisks, question marks, and brackets} {
    list [catch {glob -nocomplain goo/*} msg] $msg
} {0 {}}
test filename-14.21 {asterisks, question marks, and brackets} {
    list [catch {glob globTest/*/gorp} msg] $msg
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
	[file join $globname "weird name.c"]\
	[file join $globname x,z1.c]\
	[file join $globname x1.c]\
	[file join $globname y1.c] [file join $globname z1.c]]]]
test filename-14.26 {type specific globbing} {
    list [catch {glob -nocomplain -dir globTest -types {readonly} *} msg] $msg
} [list 0 {}]
test filename-14.27 {Bug 2710920} {unixOrWin} {
    file tail [lindex [lsort [glob globTest/*/]] 0]
} a1
test filename-14.28 {Bug 2710920} {unixOrWin} {
    file dirname [lindex [lsort [glob globTest/*/]] 0]
} globTest
test filename-14.29 {Bug 2710920} {unixOrWin} {
    file extension [lindex [lsort [glob globTest/*/]] 0]
} {}
test filename-14.30 {Bug 2710920} {unixOrWin} {
    file rootname [lindex [lsort [glob globTest/*/]] 0]
} globTest/a1/

test filename-14.31 {Bug 2918610} -setup {
    set d [makeDirectory foo]
    makeFile {} bar.soom $d
} -body {







|


|


|


|







1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
	[file join $globname "weird name.c"]\
	[file join $globname x,z1.c]\
	[file join $globname x1.c]\
	[file join $globname y1.c] [file join $globname z1.c]]]]
test filename-14.26 {type specific globbing} {
    list [catch {glob -nocomplain -dir globTest -types {readonly} *} msg] $msg
} [list 0 {}]
test filename-14.27 {Bug 2710920} {unixOrPc} {
    file tail [lindex [lsort [glob globTest/*/]] 0]
} a1
test filename-14.28 {Bug 2710920} {unixOrPc} {
    file dirname [lindex [lsort [glob globTest/*/]] 0]
} globTest
test filename-14.29 {Bug 2710920} {unixOrPc} {
    file extension [lindex [lsort [glob globTest/*/]] 0]
} {}
test filename-14.30 {Bug 2710920} {unixOrPc} {
    file rootname [lindex [lsort [glob globTest/*/]] 0]
} globTest/a1/

test filename-14.31 {Bug 2918610} -setup {
    set d [makeDirectory foo]
    makeFile {} bar.soom $d
} -body {
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
    # first.
    concat \
      [list [catch {glob -nocomplain ~wontexist ~blahxyz ~} res1] $res1] \
      [list [catch {glob -nocomplain ~ ~blahxyz ~wontexist} res2] $res2]
} {1 {user "wontexist" doesn't exist} 1 {user "blahxyz" doesn't exist}}
test filename-15.4.2 {no complain: errors, sequencing} {
    # test used to fail because if an error occurs, the interp's result
    # is reset...
    string equal \
      [list [catch {glob -nocomplain ~wontexist *} res1] $res1] \
      [list [catch {glob -nocomplain * ~wontexist} res2] $res2]
} {1}
test filename-15.5 {unix specific globbing} {unix nonPortable} {
    glob ~ouster/.csh*
} "/home/ouster/.cshrc"
catch {close [open globTest/odd\\\[\]*?\{\}name w]}
test filename-15.6 {unix specific globbing} {unix} {
    global env
    set temp $env(HOME)
    set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
    set result [list [catch {glob ~} msg] $msg]
    set env(HOME) $temp
    set result







|







|







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
    # first.
    concat \
      [list [catch {glob -nocomplain ~wontexist ~blahxyz ~} res1] $res1] \
      [list [catch {glob -nocomplain ~ ~blahxyz ~wontexist} res2] $res2]
} {1 {user "wontexist" doesn't exist} 1 {user "blahxyz" doesn't exist}}
test filename-15.4.2 {no complain: errors, sequencing} {
    # test used to fail because if an error occurs, the interp's result
    # is reset... 
    string equal \
      [list [catch {glob -nocomplain ~wontexist *} res1] $res1] \
      [list [catch {glob -nocomplain * ~wontexist} res2] $res2]
} {1}
test filename-15.5 {unix specific globbing} {unix nonPortable} {
    glob ~ouster/.csh*
} "/home/ouster/.cshrc"
catch {close [open globTest/odd\\\[\]*?\{\}name w]} 
test filename-15.6 {unix specific globbing} {unix} {
    global env
    set temp $env(HOME)
    set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
    set result [list [catch {glob ~} msg] $msg]
    set env(HOME) $temp
    set result
1493
1494
1495
1496
1497
1498
1499

1500





1501
1502
1503
1504
1505
1506
1507
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}
test filename-16.10 {windows specific globbing} {win} {
    lsort [glob -nocomplain c:globTest\\\\*.bat]
} {c:globTest/x1.BAT c:globTest/y1.Bat c:globTest/z1.bat}
test filename-16.11 {windows specific globbing} {win} {
    lsort [glob -nocomplain c:\\\\globTest\\\\*.bat]
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}

# some tests require a shared C drive





test filename-16.12 {windows specific globbing} {win sharedCdrive} {
    cd //[info hostname]/c
    glob //[info hostname]/c/*Test
} //[info hostname]/c/globTest
test filename-16.13 {windows specific globbing} {win sharedCdrive} {
    cd //[info hostname]/c
    glob "\\\\\\\\[info hostname]\\\\c\\\\*Test"







>

>
>
>
>
>







1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}
test filename-16.10 {windows specific globbing} {win} {
    lsort [glob -nocomplain c:globTest\\\\*.bat]
} {c:globTest/x1.BAT c:globTest/y1.Bat c:globTest/z1.bat}
test filename-16.11 {windows specific globbing} {win} {
    lsort [glob -nocomplain c:\\\\globTest\\\\*.bat]
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}

# some tests require a shared C drive

if {[testConstraint win]} {
    testConstraint sharedCdrive [expr {![catch {cd //[info hostname]/c}]}]
}

test filename-16.12 {windows specific globbing} {win sharedCdrive} {
    cd //[info hostname]/c
    glob //[info hostname]/c/*Test
} //[info hostname]/c/globTest
test filename-16.13 {windows specific globbing} {win sharedCdrive} {
    cd //[info hostname]/c
    glob "\\\\\\\\[info hostname]\\\\c\\\\*Test"
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
if {[testConstraint win]} {
    cd $oldDir
}

test filename-17.1 {windows specific special files} {testsetplatform} {
    testsetplatform win
    list [file pathtype com1] [file pathtype con] [file pathtype lpt3] \
	[file pathtype prn] [file pathtype nul] [file pathtype aux] \
	[file pathtype foo]
} {absolute absolute absolute absolute absolute absolute relative}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}

test filename-17.2 {windows specific glob with executable} {win} {
    makeDirectory execglob







|
|







1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
if {[testConstraint win]} {
    cd $oldDir
}

test filename-17.1 {windows specific special files} {testsetplatform} {
    testsetplatform win
    list [file pathtype com1] [file pathtype con] [file pathtype lpt3] \
      [file pathtype prn] [file pathtype nul] [file pathtype aux] \
      [file pathtype foo]
} {absolute absolute absolute absolute absolute absolute relative}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}

test filename-17.2 {windows specific glob with executable} {win} {
    makeDirectory execglob
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655

1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667

1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
    makeFile {} TAGS $d
} -body {
    llength [glob -nocomplain -directory $d -types {} -- URGENT Urkle]
} -cleanup {
    removeFile TAGS $d
    removeDirectory foo
} -result 0

test fileName-20.5 {Bug 2837800} -setup {
    set dd [makeDirectory isolate]
    set d [makeDirectory ./~foo $dd]
    makeFile {} test $d
    set savewd [pwd]
    cd $dd
} -body {
    glob -nocomplain */test
} -cleanup {
    cd $savewd
    removeFile test $d
    removeDirectory ./~foo $dd
    removeDirectory isolate
} -result ~foo/test

test fileName-20.6 {Bug 2837800} -setup {
    # Recall that we have $env(HOME) set so that references
    # to ~ point to [temporaryDirectory]
    makeFile {} test ~
    set dd [makeDirectory isolate]
    set d [makeDirectory ./~ $dd]
    set savewd [pwd]
    cd $dd
} -body {
    glob -nocomplain */test
} -cleanup {
    cd $savewd
    removeDirectory ./~ $dd
    removeDirectory isolate
    removeFile test ~
} -result {}

test fileName-20.7 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {
    file exists [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -result 1

test fileName-20.8 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {
    file tail [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -result ./~test

test fileName-20.9 {globbing for special chars} -setup {
    makeFile {} test ~
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ test
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile test ~
} -result ~/test

test fileName-20.10 {globbing for special chars} -setup {
    set s [makeDirectory sub ~]
    makeFile {} fileName-20.10 $s
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~
} -result ~/sub/fileName-20.10

# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
set env(HOME) $oldhome
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
    catch {unset platform}
}
catch {unset oldhome temp result globPreResult}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>














>
















>












>












>
|











>
|













|













<
<
<
<
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715




    makeFile {} TAGS $d
} -body {
    llength [glob -nocomplain -directory $d -types {} -- URGENT Urkle]
} -cleanup {
    removeFile TAGS $d
    removeDirectory foo
} -result 0

test fileName-20.5 {Bug 2837800} -setup {
    set dd [makeDirectory isolate]
    set d [makeDirectory ./~foo $dd]
    makeFile {} test $d
    set savewd [pwd]
    cd $dd
} -body {
    glob -nocomplain */test
} -cleanup {
    cd $savewd
    removeFile test $d
    removeDirectory ./~foo $dd
    removeDirectory isolate
} -result ~foo/test

test fileName-20.6 {Bug 2837800} -setup {
    # Recall that we have $env(HOME) set so that references
    # to ~ point to [temporaryDirectory]
    makeFile {} test ~
    set dd [makeDirectory isolate]
    set d [makeDirectory ./~ $dd]
    set savewd [pwd]
    cd $dd
} -body {
    glob -nocomplain */test
} -cleanup {
    cd $savewd
    removeDirectory ./~ $dd
    removeDirectory isolate
    removeFile test ~
} -result {}

test fileName-20.7 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {
    file exists [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -result 1

test fileName-20.8 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {
    file tail [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -result ./~test

test fileName-20.9 {} -setup {
    makeFile {} test ~
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ test
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile test ~
} -result ~/test

test fileName-20.10 {} -setup {
    set s [makeDirectory sub ~]
    makeFile {} fileName-20.10 $s
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~
} -result ~/sub/fileName-20.10

# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
set env(HOME) $oldhome
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
    catch {unset platform}
}
catch {unset oldhome temp result globPreResult}
::tcltest::cleanupTests
return




Changes to tests/fileSystem.test.

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    file link dir.link dir.dir
    cd dir.dir
    file link [file join dirinside.link] \
	[file join dirinside.dir]
    cd ..
}]}]

testConstraint haveDdeDll [llength \
	[glob -nocomplain -directory [file dirname [info nameof]] \
		*dde*[info sharedlib]]]

if {[testConstraint testsetplatform]} {
    set platform [testgetplatform]
}

test filesystem-1.0 {link normalisation} {hasLinks} {
   string equal [file normalize gorp.file] [file normalize link.file]
} {0}







<
<
<
<







81
82
83
84
85
86
87




88
89
90
91
92
93
94
    file link dir.link dir.dir
    cd dir.dir
    file link [file join dirinside.link] \
	[file join dirinside.dir]
    cd ..
}]}]





if {[testConstraint testsetplatform]} {
    set platform [testgetplatform]
}

test filesystem-1.0 {link normalisation} {hasLinks} {
   string equal [file normalize gorp.file] [file normalize link.file]
} {0}
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.40 {file normalisation with repeated separators} {
    set a [file norm foo////bar]
    set b [file norm foo/bar]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.41 {file normalisation with repeated separators} {win} {
    set a [file norm foo\\\\\\bar]
    set b [file norm foo/bar]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.42 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/..]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.42.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.43 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../..]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.43.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../../]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.44 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../../bar]
    set b [file norm /bar]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.45 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../../bar]
    set b [file norm /bar]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.46 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../bar]
    set b [file norm /bar]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.47 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /..]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.48 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.49 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /.]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.50 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /./]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.51 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../..]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../../]
    set b [file norm /]

    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.52 {bug f9f390d0fa: file join where strep is not canonical} -constraints unix -body {







|









|









|









|









|









|









|









|









|









|









|









|









|









|









|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.40 {file normalisation with repeated separators} {
    set a [file norm foo////bar]
    set b [file norm foo/bar]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.41 {file normalisation with repeated separators} {win} {
    set a [file norm foo\\\\\\bar]
    set b [file norm foo/bar]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.42 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/..]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.42.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.43 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../..]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.43.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../../]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.44 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/foo/../../bar]
    set b [file norm /bar]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.45 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../../bar]
    set b [file norm /bar]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.46 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /xxx/../bar]
    set b [file norm /bar]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.47 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /..]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.48 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.49 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /.]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.50 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /./]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.51 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../..]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} {
    set a [file norm /../../]
    set b [file norm /]
    
    if {![string equal $a $b]} {
        set res "Paths should be equal: $a , $b"
    } else {
        set res "ok"
    }
} {ok}
test filesystem-1.52 {bug f9f390d0fa: file join where strep is not canonical} -constraints unix -body {
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
} [list 1 "couldn't open \"foo\x00\": filename is invalid on this platform"]

# Make sure the testfilesystem hasn't been registered.
if {[testConstraint testfilesystem]} {
    while {![catch {testfilesystem 0}]} {}
}

test filesystem-7.1 {load from vfs} {win testsimplefilesystem haveDdeDll} {
    # This may cause a crash on exit
    set dir [pwd]
    cd [file dirname [info nameof]]
    set dde [lindex [glob *dde*[info sharedlib]] 0]
    testsimplefilesystem 1
    # This loads dde via a complex copy-to-temp operation
    load simplefs:/$dde Dde
    testsimplefilesystem 0
    cd $dir
    set res "ok"
    # The real result of this test is what happens when Tcl exits.
} {ok}
test filesystem-7.2 {cross-filesystem copy from vfs maintains mtime} \
  {testsimplefilesystem} {







|






|







745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
} [list 1 "couldn't open \"foo\x00\": filename is invalid on this platform"]

# Make sure the testfilesystem hasn't been registered.
if {[testConstraint testfilesystem]} {
    while {![catch {testfilesystem 0}]} {}
}

test filesystem-7.1 {load from vfs} {win testsimplefilesystem} {
    # This may cause a crash on exit
    set dir [pwd]
    cd [file dirname [info nameof]]
    set dde [lindex [glob *dde*[info sharedlib]] 0]
    testsimplefilesystem 1
    # This loads dde via a complex copy-to-temp operation
    load simplefs:/$dde dde
    testsimplefilesystem 0
    cd $dir
    set res "ok"
    # The real result of this test is what happens when Tcl exits.
} {ok}
test filesystem-7.2 {cross-filesystem copy from vfs maintains mtime} \
  {testsimplefilesystem} {
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
    cd abc
    set f "foo"
    set res {}
    lappend res [file exists $f]
    lappend res [file exists $f]
    cd ..
    cd def
    # If we haven't cleared the object's cwd cache, Tcl
    # will think it still exists.
    lappend res [file exists $f]
    lappend res [file exists $f]
    removeFile [file join abc foo]
    removeDirectory abc
    removeDirectory def
    cd $dir







|







971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
    cd abc
    set f "foo"
    set res {}
    lappend res [file exists $f]
    lappend res [file exists $f]
    cd ..
    cd def
    # If we haven't cleared the object's cwd cache, Tcl 
    # will think it still exists.
    lappend res [file exists $f]
    lappend res [file exists $f]
    removeFile [file join abc foo]
    removeDirectory abc
    removeDirectory def
    cd $dir
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
    cd [tcltest::temporaryDirectory]
    file mkdir dgp
    close [open dgp/test w]
    foreach relative [glob -nocomplain [file join * test]] {
	set absolute [file join [pwd] $relative]
	set res [list [file tail $absolute] "test"]
    }
    file delete -force dgp
    cd $origdir
    set res
} {test test}
test filesystem-9.6 {path objects and file tail and object rep} win {
    set res {}
    set p "C:\\toto"
    lappend res [file join $p toto]







|







1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
    cd [tcltest::temporaryDirectory]
    file mkdir dgp
    close [open dgp/test w]
    foreach relative [glob -nocomplain [file join * test]] {
	set absolute [file join [pwd] $relative]
	set res [list [file tail $absolute] "test"]
    }
    file delete -force dgp 
    cd $origdir
    set res
} {test test}
test filesystem-9.6 {path objects and file tail and object rep} win {
    set res {}
    set p "C:\\toto"
    lappend res [file join $p toto]

Changes to tests/format.test.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# %u output depends on word length, so this test is not portable.
testConstraint longIs32bit [expr {int(0x80000000) < 0}]
testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
testConstraint wideIs64bit \
	[expr {(wide(0x80000000) > 0) && (wide(0x8000000000000000) < 0)}]
testConstraint wideBiggerThanInt [expr {wide(0x80000000) != int(0x80000000)}]
# MSVC uses a broken libc that gets sprintf("%g") wrong. This is a pain
# particularly in Continuous Integration, and there isn't anything much we can
# do about it.
testConstraint notWinCI [expr {
    ($::tcl_platform(platform) ne "windows") || ![info exists ::env(CI)]}]

test format-1.1 {integer formatting} {
    format "%*d %d %d %d" 6 34 16923 -12 -1
} {    34 16923 -12 -1}
test format-1.2 {integer formatting} {
    format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
} {   6   34 16923  -12 -1 0xe 0XC}
test format-1.3 {integer formatting} longIs32bit {







<
<
<
<
<
|







17
18
19
20
21
22
23





24
25
26
27
28
29
30
31

# %u output depends on word length, so this test is not portable.
testConstraint longIs32bit [expr {int(0x80000000) < 0}]
testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
testConstraint wideIs64bit \
	[expr {(wide(0x80000000) > 0) && (wide(0x8000000000000000) < 0)}]
testConstraint wideBiggerThanInt [expr {wide(0x80000000) != int(0x80000000)}]






test format-1.1 {integer formatting} {
    format "%*d %d %d %d" 6 34 16923 -12 -1
} {    34 16923 -12 -1}
test format-1.2 {integer formatting} {
    format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
} {   6   34 16923  -12 -1 0xe 0XC}
test format-1.3 {integer formatting} longIs32bit {
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

test format-6.1 {floating-point zeroes} {eformat} {
    format "%e %f %g" 0.0 0.0 0.0 0.0
} {0.000000e+00 0.000000 0}
test format-6.2 {floating-point zeroes} {eformat} {
    format "%.4e %.4f %.4g" 0.0 0.0 0.0 0.0
} {0.0000e+00 0.0000 0}
test format-6.3 {floating-point zeroes} {eformat notWinCI} {
    format "%#.4e %#.4f %#.4g" 0.0 0.0 0.0 0.0
} {0.0000e+00 0.0000 0.000}
test format-6.4 {floating-point zeroes} {eformat} {
    format "%.0e %.0f %.0g" 0.0 0.0 0.0 0.0
} {0e+00 0 0}
test format-6.5 {floating-point zeroes} {eformat notWinCI} {
    format "%#.0e %#.0f %#.0g" 0.0 0.0 0.0 0.0
} {0.e+00 0. 0.}
test format-6.6 {floating-point zeroes} {
    format "%3.0f %3.0f %3.0f %3.0f" 0.0 0.0 0.0 0.0
} {  0   0   0   0}
test format-6.7 {floating-point zeroes} {
    format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001







|





|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

test format-6.1 {floating-point zeroes} {eformat} {
    format "%e %f %g" 0.0 0.0 0.0 0.0
} {0.000000e+00 0.000000 0}
test format-6.2 {floating-point zeroes} {eformat} {
    format "%.4e %.4f %.4g" 0.0 0.0 0.0 0.0
} {0.0000e+00 0.0000 0}
test format-6.3 {floating-point zeroes} {eformat} {
    format "%#.4e %#.4f %#.4g" 0.0 0.0 0.0 0.0
} {0.0000e+00 0.0000 0.000}
test format-6.4 {floating-point zeroes} {eformat} {
    format "%.0e %.0f %.0g" 0.0 0.0 0.0 0.0
} {0e+00 0 0}
test format-6.5 {floating-point zeroes} {eformat} {
    format "%#.0e %#.0f %#.0g" 0.0 0.0 0.0 0.0
} {0.e+00 0. 0.}
test format-6.6 {floating-point zeroes} {
    format "%3.0f %3.0f %3.0f %3.0f" 0.0 0.0 0.0 0.0
} {  0   0   0   0}
test format-6.7 {floating-point zeroes} {
    format "%3.0f %3.0f %3.0f %3.0f" 1.0 1.1 1.01 1.001
532
533
534
535
536
537
538

539
540
541

542
543

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560

561
562
563

564
565
566
567
568
569
570
} 1.000000

test format-18.1 {do not demote existing numeric values} {
    set a 0xaaaaaaaa
    # Ensure $a and $b are separate objects
    set b 0xaaaa
    append b aaaa

    set result [expr {$a == $b}]
    format %08lx $b
    lappend result [expr {$a == $b}]

    set b 0xaaaa
    append b aaaa

    lappend result [expr {$a == $b}]
    format %08x $b
    lappend result [expr {$a == $b}]
} {1 1 1 1}
test format-18.2 {do not demote existing numeric values} {wideBiggerThanInt} {
    set a [expr {0xaaaaaaaaaa + 1}]
    set b 0xaaaaaaaaab
    list [format %08x $a] [expr {$a == $b}]
} {aaaaaaab 1}

test format-19.1 {
    regression test - tcl-core message by Brian Griffin on
    26 0ctober 2004
} -body {
    set x 0x8fedc654
    list [expr { ~ $x }] [format %08x [expr { ~$x }]]
} -match regexp -result {-2414724693 f*701239ab}

test format-19.2 {Bug 1867855} {
    format %llx 0
} 0

test format-19.3 {Bug 2830354} {
    string length [format %340f 0]
} 340

test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} \
-constraints {longIs32bit} -body {
    # in case of overflow into negative, it produces width -2 (and limit exceeded),







>



>


>

















>



>







527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
} 1.000000

test format-18.1 {do not demote existing numeric values} {
    set a 0xaaaaaaaa
    # Ensure $a and $b are separate objects
    set b 0xaaaa
    append b aaaa

    set result [expr {$a == $b}]
    format %08lx $b
    lappend result [expr {$a == $b}]

    set b 0xaaaa
    append b aaaa

    lappend result [expr {$a == $b}]
    format %08x $b
    lappend result [expr {$a == $b}]
} {1 1 1 1}
test format-18.2 {do not demote existing numeric values} {wideBiggerThanInt} {
    set a [expr {0xaaaaaaaaaa + 1}]
    set b 0xaaaaaaaaab
    list [format %08x $a] [expr {$a == $b}]
} {aaaaaaab 1}

test format-19.1 {
    regression test - tcl-core message by Brian Griffin on
    26 0ctober 2004
} -body {
    set x 0x8fedc654
    list [expr { ~ $x }] [format %08x [expr { ~$x }]]
} -match regexp -result {-2414724693 f*701239ab}

test format-19.2 {Bug 1867855} {
    format %llx 0
} 0

test format-19.3 {Bug 2830354} {
    string length [format %340f 0]
} 340

test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} \
-constraints {longIs32bit} -body {
    # in case of overflow into negative, it produces width -2 (and limit exceeded),

Changes to tests/info.test.

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792






## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
test info-23.0 {eval'd info frame} -constraints {!singleTestInterp} -body {
    list [i eval {info frame}] [i eval {eval {info frame}}]
} -setup {interp create i} -cleanup {interp delete i} -result {1 2}
test info-23.1 {eval'd info frame, semi-dynamic} -constraints {!singleTestInterp} -body {
    i eval {eval info frame}
} -setup {interp create i} -cleanup {interp delete i} -result 2
test info-23.2 {eval'd info frame, dynamic} -constraints {!singleTestInterp} -body {
    i eval {	set script {info frame}
		eval $script}
} -setup {interp create i} -cleanup {interp delete i} -result 2
test info-23.3 {eval'd info frame, literal} -match glob -body {
    eval {
	info frame 0
    }
} -result {type source line 788 file * cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.4 {eval'd info frame, semi-dynamic} {
    eval info frame 0







|
|
|
|
|
|
|
|
|
|







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792






## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
test info-23.0 {eval'd info frame} {!singleTestInterp} {
    eval {info frame}
} 8
test info-23.1 {eval'd info frame, semi-dynamic} {!singleTestInterp} {
    eval info frame
} 8
test info-23.2 {eval'd info frame, dynamic} {!singleTestInterp} {
    set script {info frame}
    eval $script
} 8
test info-23.3 {eval'd info frame, literal} -match glob -body {
    eval {
	info frame 0
    }
} -result {type source line 788 file * cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.4 {eval'd info frame, semi-dynamic} {
    eval info frame 0

Changes to tests/init.test.

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
    package require tcltest 2.3.4
    namespace import -force ::tcltest::*
}

# Clear out any namespaces called test_ns_*
catch {namespace delete {*}[namespace children :: test_ns_*]}

test init-0.1 {no error on initialization phase (init.tcl)} -setup {
    interp create child
} -body {
    child eval {
	list [set v [info exists ::errorInfo]] \
		[if {$v} {set ::errorInfo}] \
	     [set v [info exists ::errorCode]] \
		[if {$v} {set ::errorCode}]
    }
} -cleanup {
    interp delete child
} -result {0 {} 0 {}}

# Six cases - white box testing

test init-1.1 {auto_qualify - absolute cmd - namespace} {
    auto_qualify ::foo::bar ::blue
} ::foo::bar

test init-1.2 {auto_qualify - absolute cmd - global} {







<
<
<
<
<
<
<
<
<
<
<
<
<







14
15
16
17
18
19
20













21
22
23
24
25
26
27
    package require tcltest 2.3.4
    namespace import -force ::tcltest::*
}

# Clear out any namespaces called test_ns_*
catch {namespace delete {*}[namespace children :: test_ns_*]}














# Six cases - white box testing

test init-1.1 {auto_qualify - absolute cmd - namespace} {
    auto_qualify ::foo::bar ::blue
} ::foo::bar

test init-1.2 {auto_qualify - absolute cmd - global} {
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
} ::foo::bar

test init-1.8 {auto_qualify - multiple colons 2} {
    auto_qualify :::foo ::bar
} foo


# we use a child interp and auto_reset and double the tests because there is 2
# places where auto_loading occur (before loading the indexes files and after)

set testInterp [interp create]
tcltest::loadIntoChildInterpreter $testInterp {*}$argv
interp eval $testInterp {
    namespace import -force ::tcltest::*
    auto_reset
    catch {rename parray {}}

test init-2.0 {load parray - stage 1} {
    set ret [catch {parray} error]







|



|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
} ::foo::bar

test init-1.8 {auto_qualify - multiple colons 2} {
    auto_qualify :::foo ::bar
} foo


# we use a sub interp and auto_reset and double the tests because there is 2
# places where auto_loading occur (before loading the indexes files and after)

set testInterp [interp create]
tcltest::loadIntoSlaveInterpreter $testInterp {*}$argv
interp eval $testInterp {
    namespace import -force ::tcltest::*
    auto_reset
    catch {rename parray {}}

test init-2.0 {load parray - stage 1} {
    set ret [catch {parray} error]

Deleted tests/internals.tcl.

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
# This file contains internal facilities for Tcl tests.
#
# Source this file in the related tests to include from tcl-tests:
#
#   source [file join [file dirname [info script]] internals.tcl]
#
# Copyright (c) 2020 Sergey G. Brester (sebres).
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[namespace which -command ::tcltest::internals::scriptpath] eq ""} {namespace eval ::tcltest::internals {

namespace path ::tcltest

::tcltest::ConstraintInitializer testWithLimit { expr {[testConstraint macOrUnix] && ![catch { exec prlimit --version }]} }

# test-with-limit --
#
# Usage: test-with-limit ?-addmem bytes? ?-maxmem bytes? command
# Options:
#	-addmem - set additional memory limit (in bytes) as difference (extra memory needed to run a test)
#	-maxmem - set absolute maximum address space limit (in bytes)
# 
proc testWithLimit args {
    set body [lindex $args end]
    array set in [lrange $args 0 end-1]
    # test in child process (with limits):
    set pipe {}
    if {[catch {
	# start new process:
	set pipe [open |[list [interpreter]] r+]
	set ppid [pid $pipe]
	# create prlimit args:
	set args {}
	# with limited address space:
	if {[info exists in(-addmem)] || [info exists in(-maxmem)]} {
	    if {[info exists in(-addmem)]} {
		# as differnce to normal usage, so try to retrieve current memory usage:
		if {[catch {
		    # using ps (vsz is in KB):
		    incr in(-addmem) [expr {[lindex [exec ps -hq $ppid -o vsz] end] * 1024}]
		}]} {
		    # ps failed, use default size 20MB:
		    incr in(-addmem) 20000000
		    # + size of locale-archive (may be up to 100MB):
		    incr in(-addmem) [expr {
			[file exists /usr/lib/locale/locale-archive] ? 
			[file size /usr/lib/locale/locale-archive] : 0
		    }]
		}
		if {![info exists in(-maxmem)]} {
		    set in(-maxmem) $in(-addmem)
		}
		set in(-maxmem) [expr { max($in(-addmem), $in(-maxmem)) }]
	    }
	    append args --as=$in(-maxmem)
	}
	# apply limits:
	exec prlimit -p $ppid {*}$args
    } msg opt]} {
	catch {close $pipe}
	tcltest::Warn "testWithLimit: error - [regsub {^\s*([^\n]*).*$} $msg {\1}]"
	tcltest::Skip testWithLimit
    }
    # execute body, close process and return:
    set ret [catch {
	chan configure $pipe -buffering line
	puts $pipe "puts \[$body\]"
	puts $pipe exit
	set result [read $pipe]
	close $pipe
	set pipe {}
	set result
    } result opt]
    if {$pipe ne ""} { catch { close $pipe } }
    if {$ret && [dict get $opt -errorcode] eq "BYPASS-SKIPPED-TEST"} {
	return {*}$opt $result
    }
    if { ( [info exists in(-warn-on-code)] && $ret in $in(-warn-on-code) )
      || ( $ret && [info exists in(-warn-on-alloc-error)] && $in(-warn-on-alloc-error)
      	    && [regexp {\munable to (?:re)?alloc\M} $result] )
    } {
	tcltest::Warn "testWithLimit: wrong limit, result: $result"
	tcltest::Skip testWithLimit
    }
    return {*}$opt $result
}

# export all routines starting with test
namespace export test*

# for script path & as mark for loaded
proc scriptpath {} [list return [info script]]

}}; # end of internals.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































Changes to tests/interp.test.

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
    list [catch {interp hello} msg] $msg
} {1 {bad option "hello": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.8 {options for interp command} {
    list [catch {interp -froboz} msg] $msg
} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.9 {options for interp command} {
    list [catch {interp -froboz -safe} msg] $msg
} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.10 {options for interp command} {
    list [catch {interp target} msg] $msg
} {1 {wrong # args: should be "interp target path alias"}}


# Part 1: Basic interpreter creation tests:
test interp-2.1 {basic interpreter creation} {
    interp create a
} a
test interp-2.2 {basic interpreter creation} {
    catch {interp create}
} 0
test interp-2.3 {basic interpreter creation} {
    catch {interp create -safe}
} 0
test interp-2.4 {basic interpreter creation} {
    list [catch {interp create a} msg] $msg
} {1 {interpreter named "a" already exists, cannot create}}
test interp-2.5 {basic interpreter creation} {
    interp create b -safe
} b
test interp-2.6 {basic interpreter creation} {







|














|







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
    list [catch {interp hello} msg] $msg
} {1 {bad option "hello": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.8 {options for interp command} {
    list [catch {interp -froboz} msg] $msg
} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.9 {options for interp command} {
    list [catch {interp -froboz -safe} msg] $msg
} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}} 
test interp-1.10 {options for interp command} {
    list [catch {interp target} msg] $msg
} {1 {wrong # args: should be "interp target path alias"}}


# Part 1: Basic interpreter creation tests:
test interp-2.1 {basic interpreter creation} {
    interp create a
} a
test interp-2.2 {basic interpreter creation} {
    catch {interp create}
} 0
test interp-2.3 {basic interpreter creation} {
    catch {interp create -safe}
} 0 
test interp-2.4 {basic interpreter creation} {
    list [catch {interp create a} msg] $msg
} {1 {interpreter named "a" already exists, cannot create}}
test interp-2.5 {basic interpreter creation} {
    interp create b -safe
} b
test interp-2.6 {basic interpreter creation} {
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum > $thenum
} 1
test interp-2.12 {anonymous interps vs existing procs} {
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum - $thenum
} 1
test interp-2.13 {correct default when no $path arg is given} -body {
    interp create --
} -match regexp -result {interp[0-9]+}

foreach i [interp slaves] {
    interp delete $i
}

# Part 2: Testing "interp slaves" and "interp exists"
test interp-3.1 {testing interp exists and interp slaves} {
    interp slaves







|








|



|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum > $thenum
} 1    
test interp-2.12 {anonymous interps vs existing procs} {
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum - $thenum
} 1    
test interp-2.13 {correct default when no $path arg is given} -body {
    interp create --
} -match regexp -result {interp[0-9]+}
    
foreach i [interp slaves] {
    interp delete $i
}

# Part 2: Testing "interp slaves" and "interp exists"
test interp-3.1 {testing interp exists and interp slaves} {
    interp slaves
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
    proc dela {} {interp delete a}
    list [catch {a eval foo} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}
test interp-18.9 {eval in deleted interp, bug 495830} {
    interp create tst
    interp alias tst suicide {} interp delete tst
    list [catch {tst eval {suicide; set a 5}} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}
test interp-18.10 {eval in deleted interp, bug 495830} {
    interp create tst
    interp alias tst suicide {} interp delete tst
    list [catch {tst eval {set set set; suicide; $set a 5}} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}

# Test alias deletion

test interp-19.1 {alias deletion} {
    catch {interp delete a}
    interp create a
    interp alias a foo a bar







|




|







850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
    proc dela {} {interp delete a}
    list [catch {a eval foo} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}
test interp-18.9 {eval in deleted interp, bug 495830} {
    interp create tst
    interp alias tst suicide {} interp delete tst
    list [catch {tst eval {suicide; set a 5}} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}     
test interp-18.10 {eval in deleted interp, bug 495830} {
    interp create tst
    interp alias tst suicide {} interp delete tst
    list [catch {tst eval {set set set; suicide; $set a 5}} msg] $msg
} {1 {attempt to call eval in deleted interpreter}}     

# Test alias deletion

test interp-19.1 {alias deletion} {
    catch {interp delete a}
    interp create a
    interp alias a foo a bar
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
    interp alias a foo a bar
    interp eval a rename foo blotz
    interp eval a {proc foo {} {expr 34 * 34}}
    interp alias a foo {}
    set l [interp eval a foo]
    interp delete a
    set l
} 1156

test interp-20.1 {interp hide, interp expose and interp invokehidden} {
    set a [interp create]
    $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
    $a eval {proc foo {} {}}
    $a hide foo
    catch {$a eval foo something} msg







|







945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
    interp alias a foo a bar
    interp eval a rename foo blotz
    interp eval a {proc foo {} {expr 34 * 34}}
    interp alias a foo {}
    set l [interp eval a foo]
    interp delete a
    set l
} 1156    

test interp-20.1 {interp hide, interp expose and interp invokehidden} {
    set a [interp create]
    $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
    $a eval {proc foo {} {}}
    $a hide foo
    catch {$a eval foo something} msg
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
    interp delete a
    set l
} {{[list x y z] f g h} z}
test interp-20.21 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.22 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.23 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a eval {interp hide {} list}} msg]
    lappend l $msg
    interp delete a
    set l
} {1 {permission denied: safe interpreter cannot hide commands}}
test interp-20.24 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {a eval {interp hide b list}} msg]
    lappend l $msg
    interp delete a
    set l
} {1 {permission denied: safe interpreter cannot hide commands}}
test interp-20.25 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.26 {interp expoose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]
    lappend l $msg
    lappend l [catch {a expose list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.27 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]
    lappend l $msg
    lappend l [catch {interp expose a list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.28 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]
    lappend l $msg
    lappend l [catch {a eval {interp expose {} list}} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.29 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]
    lappend l $msg
    lappend l [catch {a eval {interp expose {} list}} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.30 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]
    lappend l $msg
    lappend l [catch {a eval {interp expose b list}} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.31 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]
    lappend l $msg
    lappend l [catch {interp expose {a b} list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.32 {interp invokehidden vs safety} {







|








|








|









|


















|










|

|








|










|

|









|

|









|







1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
    interp delete a
    set l
} {{[list x y z] f g h} z}
test interp-20.21 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]    
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.22 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]    
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.23 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a eval {interp hide {} list}} msg]    
    lappend l $msg
    interp delete a
    set l
} {1 {permission denied: safe interpreter cannot hide commands}}
test interp-20.24 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {a eval {interp hide b list}} msg]    
    lappend l $msg
    interp delete a
    set l
} {1 {permission denied: safe interpreter cannot hide commands}}
test interp-20.25 {interp hide vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {}}
test interp-20.26 {interp expoose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]    
    lappend l $msg
    lappend l [catch {a expose list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.27 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]    
    lappend l $msg
    lappend l [catch {interp expose a list} msg]    
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.28 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {a hide list} msg]    
    lappend l $msg
    lappend l [catch {a eval {interp expose {} list}} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.29 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [catch {interp hide a list} msg]    
    lappend l $msg
    lappend l [catch {a eval {interp expose {} list}} msg]    
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.30 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]    
    lappend l $msg
    lappend l [catch {a eval {interp expose b list}} msg]    
    lappend l $msg
    interp delete a
    set l
} {0 {} 1 {permission denied: safe interpreter cannot expose commands}}
test interp-20.31 {interp expose vs safety} {
    catch {interp delete a}
    interp create a -safe
    interp create {a b}
    set l ""
    lappend l [catch {interp hide {a b} list} msg]    
    lappend l $msg
    lappend l [catch {interp expose {a b} list} msg]
    lappend l $msg
    interp delete a
    set l
} {0 {} 0 {}}
test interp-20.32 {interp invokehidden vs safety} {
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
} ""
test interp-21.5 {interp hidden} {
    catch {interp delete a}
    interp create -safe a
    set l [lsort [interp hidden a]]
    interp delete a
    set l
} $hidden_cmds
test interp-21.6 {interp hidden vs interp hide, interp expose} {
    catch {interp delete a}
    interp create a
    set l ""
    lappend l [interp hidden a]
    interp hide a pwd
    lappend l [interp hidden a]







|







1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
} ""
test interp-21.5 {interp hidden} {
    catch {interp delete a}
    interp create -safe a
    set l [lsort [interp hidden a]]
    interp delete a
    set l
} $hidden_cmds 
test interp-21.6 {interp hidden vs interp hide, interp expose} {
    catch {interp delete a}
    interp create a
    set l ""
    lappend l [interp hidden a]
    interp hide a pwd
    lappend l [interp hidden a]
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
    lappend l [interp hidden a]
    a alias bar {}
    lappend l [interp aliases a]
    lappend l [interp hidden a]
    interp delete a
    set l
} {{} bar {} bar bar {} {}}
test interp-23.2 {testing hiding vs aliases} {unixOrWin} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [lsort [interp hidden a]]
    a alias bar bar
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    a hide bar
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    a alias bar {}
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    interp delete a
    set l
} {{cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {bar cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload}}

test interp-24.1 {result resetting on error} {
    catch {interp delete a}
    interp create a
    proc foo args {error $args}
    interp alias a foo {} foo
    set l [interp eval a {







|















|







1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
    lappend l [interp hidden a]
    a alias bar {}
    lappend l [interp aliases a]
    lappend l [interp hidden a]
    interp delete a
    set l
} {{} bar {} bar bar {} {}}
test interp-23.2 {testing hiding vs aliases} {unixOrPc} {
    catch {interp delete a}
    interp create a -safe
    set l ""
    lappend l [lsort [interp hidden a]]
    a alias bar bar
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    a hide bar
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    a alias bar {}
    lappend l [lsort [interp aliases a]]
    lappend l [lsort [interp hidden a]]
    interp delete a
    set l
} {{cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {bar cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload}} 

test interp-24.1 {result resetting on error} {
    catch {interp delete a}
    interp create a
    proc foo args {error $args}
    interp alias a foo {} foo
    set l [interp eval a {
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
# Interps result transmission
#

test interp-26.1 {result code transmission : interp eval direct} {
    # Test that all the possibles error codes from Tcl get passed up
    # from the slave interp's context to the master, even though the
    # slave nominally thinks the command is running at the root level.

    catch {interp delete a}
    interp create a
    set res {}
    # use a for so if a return -code break 'escapes' we would notice
    for {set code -1} {$code<=5} {incr code} {
	lappend res [catch {interp eval a return -code $code} msg]
    }







|







2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
# Interps result transmission
#

test interp-26.1 {result code transmission : interp eval direct} {
    # Test that all the possibles error codes from Tcl get passed up
    # from the slave interp's context to the master, even though the
    # slave nominally thinks the command is running at the root level.
    
    catch {interp delete a}
    interp create a
    set res {}
    # use a for so if a return -code break 'escapes' we would notice
    for {set code -1} {$code<=5} {incr code} {
	lappend res [catch {interp eval a return -code $code} msg]
    }
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
    set res
} {-1 ret-1 0 ret0 1 ret1 0 ret2 3 ret3 4 ret4 5 ret5}

test interp-26.3 {result code transmission : aliases} {
    # Test that all the possibles error codes from Tcl get passed up
    # from the slave interp's context to the master, even though the
    # slave nominally thinks the command is running at the root level.

    catch {interp delete a}
    interp create a
    set res {}
    proc MyTestAlias {code} {
	return -code $code ret$code
    }
    interp alias a Test {} MyTestAlias







|







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
    set res
} {-1 ret-1 0 ret0 1 ret1 0 ret2 3 ret3 4 ret4 5 ret5}

test interp-26.3 {result code transmission : aliases} {
    # Test that all the possibles error codes from Tcl get passed up
    # from the slave interp's context to the master, even though the
    # slave nominally thinks the command is running at the root level.
    
    catch {interp delete a}
    interp create a
    set res {}
    proc MyTestAlias {code} {
	return -code $code ret$code
    }
    interp alias a Test {} MyTestAlias
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
    while executing
"test"}

# Interps & Namespaces
test interp-27.1 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} {
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    $i alias foo::bar tstAlias foo::bar;
    $i eval foo::bar test
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.2 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} {
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    $i alias foo::bar tstAlias foo::bar;
    $i eval namespace eval foo {bar test}
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.3 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} {
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    interp eval $i {namespace eval foo {proc bar {} {error "bar called"}}}
    interp alias $i foo::bar {} tstAlias foo::bar;
    interp eval $i {namespace eval foo {bar test}}
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.4 {interp aliases & namespaces} {
    set i [interp create];
    namespace eval foo2 {
	variable aliasTrace {};
	proc bar {args} {
	    variable aliasTrace;
	    lappend aliasTrace [list [namespace current] $args];
	}
    }
    $i alias foo::bar foo2::bar foo::bar;
    $i eval namespace eval foo {bar test}
    set r $foo2::aliasTrace;







|












|












|














|







2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
    while executing
"test"}

# Interps & Namespaces
test interp-27.1 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} { 
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    $i alias foo::bar tstAlias foo::bar;
    $i eval foo::bar test
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.2 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} { 
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    $i alias foo::bar tstAlias foo::bar;
    $i eval namespace eval foo {bar test}
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.3 {interp aliases & namespaces} {
    set i [interp create];
    set aliasTrace {};
    proc tstAlias {args} { 
	global aliasTrace;
	lappend aliasTrace [list [namespace current] $args];
    }
    interp eval $i {namespace eval foo {proc bar {} {error "bar called"}}}
    interp alias $i foo::bar {} tstAlias foo::bar;
    interp eval $i {namespace eval foo {bar test}}
    interp delete $i
    set aliasTrace;
} {{:: {foo::bar test}}}

test interp-27.4 {interp aliases & namespaces} {
    set i [interp create];
    namespace eval foo2 {
	variable aliasTrace {};
	proc bar {args} { 
	    variable aliasTrace;
	    lappend aliasTrace [list [namespace current] $args];
	}
    }
    $i alias foo::bar foo2::bar foo::bar;
    $i eval namespace eval foo {bar test}
    set r $foo2::aliasTrace;
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
} -result {4 0} -cleanup {
    rename cb3 {}
    rename cb4 {}
}
# Bug 1085023
test interp-34.8 {time limits trigger in vwaits} -body {
    set i [interp create]
    interp limit $i time -seconds [expr {[clock seconds] + 1}] -granularity 1
    $i eval {
	set x {}
	vwait x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}
test interp-34.9 {time limits trigger in blocking after} {
    set i [interp create]
    set t0 [clock seconds]
    interp limit $i time -seconds [expr {$t0 + 1}] -granularity 1
    set code [catch {
	$i eval {after 10000}
    } msg]
    set t1 [clock seconds]
    interp delete $i
    list $code $msg [expr {($t1-$t0) < 3 ? "OK" : $t1-$t0}]
} {1 {time limit exceeded} OK}
test interp-34.10 {time limits trigger in vwaits: Bug 1221395} -body {
    set i [interp create]
    # Assume someone hasn't set the clock to early 1970!
    $i limit time -seconds 1 -granularity 4
    interp alias $i log {} lappend result
    set result {}







|
















|







3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
} -result {4 0} -cleanup {
    rename cb3 {}
    rename cb4 {}
}
# Bug 1085023
test interp-34.8 {time limits trigger in vwaits} -body {
    set i [interp create]
    interp limit $i time -seconds [expr {[clock seconds]+1}] -granularity 1
    $i eval {
	set x {}
	vwait x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}
test interp-34.9 {time limits trigger in blocking after} {
    set i [interp create]
    set t0 [clock seconds]
    interp limit $i time -seconds [expr {$t0 + 1}] -granularity 1
    set code [catch {
	$i eval {after 10000}
    } msg]
    set t1 [clock seconds]
    interp delete $i
    list $code $msg [expr {($t1-$t0) < 3 ? "OK" : $t1-$t0}] 
} {1 {time limit exceeded} OK}
test interp-34.10 {time limits trigger in vwaits: Bug 1221395} -body {
    set i [interp create]
    # Assume someone hasn't set the clock to early 1970!
    $i limit time -seconds 1 -granularity 4
    interp alias $i log {} lappend result
    set result {}
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
    proc cb2 {} {
	global result
	lappend result cb2
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    $i limit time -seconds [expr {$t0 + 1}] -granularity 1 \
	-command "cb1 $i [expr {$t0 + 2}]"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}







|
|







3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
    proc cb2 {} {
	global result
	lappend result cb2
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    $i limit time -seconds [expr {$t0+1}] -granularity 1 \
	-command "cb1 $i [expr {$t0+2}]"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
	lappend result cb1
	set times [lassign $times t]
	$i limit time -seconds $t
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    set ::times "[expr {$t0 + 2}] [expr {$t0 + 100}]"
    $i limit time -seconds [expr {$t0 + 1}] -granularity 1 -command "cb1 $i"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}







|
|







3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
	lappend result cb1
	set times [lassign $times t]
	$i limit time -seconds $t
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    set ::times "[expr {$t0+2}] [expr {$t0+100}]"
    $i limit time -seconds [expr {$t0+1}] -granularity 1 -command "cb1 $i"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
test interp-35.24 {interp time limits can't touch current interp} -body {
    interp limit {} time -seconds 2
} -returnCodes error -result {limits on current interpreter inaccessible}

test interp-36.1 {interp bgerror syntax} -body {
    interp bgerror
} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
test interp-36.2 {interp bgerror syntax} -body {
    interp bgerror x y z
} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
test interp-36.3 {interp bgerror syntax} -setup {
    interp create slave
} -body {
    slave bgerror x y
} -cleanup {







|







3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
test interp-35.24 {interp time limits can't touch current interp} -body {
    interp limit {} time -seconds 2
} -returnCodes error -result {limits on current interpreter inaccessible}

test interp-36.1 {interp bgerror syntax} -body {
    interp bgerror
} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
test interp-36.2 {interp bgerror syntax} -body { 
    interp bgerror x y z
} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
test interp-36.3 {interp bgerror syntax} -setup {
    interp create slave
} -body {
    slave bgerror x y
} -cleanup {
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
	variable result
	set result [lindex $args 0]
    }
} -body {
    slave eval {
	variable done {}
	after 0 error foo
	after 20 [list ::set [namespace which -variable done] {}]
	vwait [namespace which -variable done]
    }
    set result
} -cleanup {
    variable result {}
    unset result
    interp delete slave







|







3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
	variable result
	set result [lindex $args 0]
    }
} -body {
    slave eval {
	variable done {}
	after 0 error foo
	after 10 [list ::set [namespace which -variable done] {}]
	vwait [namespace which -variable done]
    }
    set result
} -cleanup {
    variable result {}
    unset result
    interp delete slave

Changes to tests/io.test.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
testConstraint fileevent        [llength [info commands fileevent]]
testConstraint fcopy            [llength [info commands fcopy]]
testConstraint testfevent       [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
testConstraint testmainthread   [llength [info commands testmainthread]]
testConstraint testthread       [llength [info commands testthread]]
testConstraint testobj		[llength [info commands testobj]]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

# You need a *very* special environment to do some tests.  In
# particular, many file systems do not support large-files...
testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

# some tests can only be run is umask is 2
# if "umask" cannot be run, the tests will be skipped.







<







35
36
37
38
39
40
41

42
43
44
45
46
47
48
testConstraint fileevent        [llength [info commands fileevent]]
testConstraint fcopy            [llength [info commands fcopy]]
testConstraint testfevent       [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
testConstraint testmainthread   [llength [info commands testmainthread]]
testConstraint testthread       [llength [info commands testthread]]
testConstraint testobj		[llength [info commands testobj]]


# You need a *very* special environment to do some tests.  In
# particular, many file systems do not support large-files...
testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

# some tests can only be run is umask is 2
# if "umask" cannot be run, the tests will be skipped.
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
test io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug
    # applied to tcl will cause tcl, more specifically WriteChars, to
    # go into an infinite loop.

    set f [open $path(test2) w]
    fconfigure      $f -encoding iso2022-jp
    puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
    close           $f
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"

test io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends
    # escape bytes, check for the case where the escape
    # bytes overflow the current IO buffer. The bytes







|
|
|
|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
test io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug
    # applied to tcl will cause tcl, more specifically WriteChars, to
    # go into an infinite loop.

    set f [open $path(test2) w] 
    fconfigure      $f -encoding iso2022-jp 
    puts -nonewline $f [format %s%c [string repeat " " 4] 12399] 
    close           $f 
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"

test io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends
    # escape bytes, check for the case where the escape
    # bytes overflow the current IO buffer. The bytes
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    lappend sizes [file size $path(test2)]

    set sizes
} {19 19 19 19 19}

test io-2.1 {WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    fconfigure $f  -encoding binary -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-2.2 {WriteBytes: savedLF > 0} {







|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    lappend sizes [file size $path(test2)]

    set sizes
} {19 19 19 19 19}

test io-2.1 {WriteBytes} {
    # loop until all bytes are written
    
    set f [open $path(test1) w]
    fconfigure $f  -encoding binary -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-2.2 {WriteBytes: savedLF > 0} {
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
    close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-2.3 {WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.

    set f [open $path(test1) w]
    fconfigure $f -encoding binary -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     fconfigure $f -encoding binary -buffering line -translation lf \
	     -buffersize 16
    puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test io-3.1 {WriteChars: compatibility with WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {







|



















|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-2.3 {WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.
    
    set f [open $path(test1) w]
    fconfigure $f -encoding binary -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     fconfigure $f -encoding binary -buffering line -translation lf \
	     -buffersize 16
    puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test io-3.1 {WriteChars: compatibility with WriteBytes} {
    # loop until all bytes are written
    
    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.

    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-3.4 {WriteChars: loop over stage buffer} {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 16
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.5 {WriteChars: saved != 0} {
    # Bytes produced by UtfToExternal from end of last channel buffer
    # had to be moved to beginning of next channel buffer to preserve
    # requested buffersize.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
    # One incomplete UTF-8 character at end of staging buffer.  Backup







|











|











|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.
    
    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-3.4 {WriteChars: loop over stage buffer} {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 16 
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.5 {WriteChars: saved != 0} {
    # Bytes produced by UtfToExternal from end of last channel buffer
    # had to be moved to beginning of next channel buffer to preserve
    # requested buffersize.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17 
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
    # One incomplete UTF-8 character at end of staging buffer.  Backup
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    # When translating UTF-8 to external, the produced bytes went past end
    # of the channel buffer.  This is done purpose -- we then truncate the
    # bytes at the end of the partial character to preserve the requested
    # blocksize on flush.  The truncated bytes are moved to the beginning
    # of the next channel buffer.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.8 {WriteChars: reset sawLF after each buffer} {
    set f [open $path(test1) w]







|







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    # When translating UTF-8 to external, the produced bytes went past end
    # of the channel buffer.  This is done purpose -- we then truncate the
    # bytes at the end of the partial character to preserve the requested
    # blocksize on flush.  The truncated bytes are moved to the beginning
    # of the next channel buffer.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17 
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.8 {WriteChars: reset sawLF after each buffer} {
    set f [open $path(test1) w]
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
    puts -nonewline $f "12345678901\n456789012345678901234"
    close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    fconfigure $f
    puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]







|







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    puts -nonewline $f "12345678901\n456789012345678901234"
    close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    fconfigure $f 
    puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
    close $f
    set x
} [list 2 "\u4e00\u4e01"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test io-6.6 {Tcl_GetsObj: loop test} {
    # if (dst >= dstEnd)

    set f [open $path(test1) w]
    puts $f $a
    puts $f hi
    close $f
    set f [open $path(test1)]
    set x [list [gets $f line] $line]







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
    close $f
    set x
} [list 2 "\u4e00\u4e01"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test io-6.6 {Tcl_GetsObj: loop test} {
    # if (dst >= dstEnd) 

    set f [open $path(test1) w]
    puts $f $a
    puts $f hi
    close $f
    set f [open $path(test1)]
    set x [list [gets $f line] $line]
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [tell $f] [testchannel inputbuffered $f]]
    close $f
    set x
} [list 15 "123456789012345" 17 3]
test io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} {
    # eol still equals dstEnd

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [eof $f]]
    close $f
    set x
} [list 16 "123456789012345\r" 1]
test io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} {
    # not (*eol == '\n')

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\rabcd\r\nefg"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [tell $f]]







|











|
|







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [tell $f] [testchannel inputbuffered $f]]
    close $f
    set x
} [list 15 "123456789012345" 17 3]
test io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} {
    # eol still equals dstEnd
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [eof $f]]
    close $f
    set x
} [list 16 "123456789012345\r" 1]
test io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} {
    # not (*eol == '\n') 
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\rabcd\r\nefg"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf -buffersize 16
    set x [list [gets $f line] $line [tell $f]]
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    fconfigure $f -blocking 1
    puts -nonewline $f "\nabcd\refg\x1a"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel openpipe fileevent} {
    # not (*eol == '\n')

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    fconfigure $f -blocking 1
    puts -nonewline $f "abcd\refg\x1a"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]







|








|







|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f] 
    fconfigure $f -blocking 1
    puts -nonewline $f "\nabcd\refg\x1a"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel openpipe fileevent} {
    # not (*eol == '\n') 

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f] 
    fconfigure $f -blocking 1
    puts -nonewline $f "abcd\refg\x1a"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
    puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -buffersize 16
    set x [list [gets $f] [testchannel inputbuffered $f]]
    close $f
    set x
} [list "123456789012345" 15]
test io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} {testchannel} {
    # PeekAhead() did not get any, so (eol >= dstEnd)

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -buffersize 16
    set x [list [gets $f] [testchannel queuedcr $f]]
    close $f
    set x
} [list "123456789012345" 1]
test io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} {testchannel} {
    # if (*eol == '\n') {skip++}

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\r\n78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [testchannel queuedcr $f] [tell $f] [gets $f]]
    close $f
    set x
} [list "123456" 0 8 "78901"]
test io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} {testchannel} {
    # not (*eol == '\n')

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\r78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [testchannel queuedcr $f] [tell $f] [gets $f]]
    close $f
    set x
} [list "123456" 0 7 "78901"]
test io-6.51 {Tcl_GetsObj: auto mode: \n} {
    # else if (*eol == '\n') {goto gotoeol;}

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\n78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [tell $f] [gets $f]]
    close $f







|


|












|










|
|











|







950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -buffersize 16
    set x [list [gets $f] [testchannel inputbuffered $f]]
    close $f
    set x
} [list "123456789012345" 15]    
test io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} {testchannel} {
    # PeekAhead() did not get any, so (eol >= dstEnd)
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456789012345\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -buffersize 16
    set x [list [gets $f] [testchannel queuedcr $f]]
    close $f
    set x
} [list "123456789012345" 1]
test io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} {testchannel} {
    # if (*eol == '\n') {skip++}
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\r\n78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [testchannel queuedcr $f] [tell $f] [gets $f]]
    close $f
    set x
} [list "123456" 0 8 "78901"]
test io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} {testchannel} {
    # not (*eol == '\n') 
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\r78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [testchannel queuedcr $f] [tell $f] [gets $f]]
    close $f
    set x
} [list "123456" 0 7 "78901"]
test io-6.51 {Tcl_GetsObj: auto mode: \n} {
    # else if (*eol == '\n') {goto gotoeol;}
    
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\n78901"
    close $f
    set f [open $path(test1)]
    set x [list [gets $f] [tell $f] [gets $f]]
    close $f
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
    fconfigure $f -encoding shiftjis -buffersize 16
    set x [gets $f]
    close $f
    set x
} "1234567890123\uff10\uff11\uff12\uff13\uff14"
test io-7.2 {FilterInputBytes: split up character in middle of buffer} {
    # (bufPtr->nextAdded < bufPtr->bufLength)

    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    set x [list [gets $f line] $line [eof $f]]







|







1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
    fconfigure $f -encoding shiftjis -buffersize 16
    set x [gets $f]
    close $f
    set x
} "1234567890123\uff10\uff11\uff12\uff13\uff14"
test io-7.2 {FilterInputBytes: split up character in middle of buffer} {
    # (bufPtr->nextAdded < bufPtr->bufLength)
    
    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    set x [list [gets $f line] $line [eof $f]]
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
    # is 30).  To check if "\n" follows, calls PeekAhead and determines
    # that cached data is available in buffer w/o having to call driver.

    set x [gets $f]
    close $f
    set x
} $a
unset a
test io-8.5 {PeekAhead: don't peek if last read was short} {stdio testchannel openpipe fileevent} {
    # (bufPtr->nextAdded < bufPtr->length)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto binary}
    puts -nonewline $f "abcdefghijklmno\r"
    flush $f
    # here
    set x [list [gets $f line] $line [testchannel queuedcr $f]]
    close $f
    set x
} {15 abcdefghijklmno 1}
test io-8.6 {PeekAhead: change to non-blocking mode} {stdio testchannel openpipe fileevent} {
    # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto binary} -buffersize 16
    puts -nonewline $f "abcdefghijklmno\r"
    flush $f
    # here
    set x [list [gets $f line] $line [testchannel queuedcr $f]]







|















|







1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
    # is 30).  To check if "\n" follows, calls PeekAhead and determines
    # that cached data is available in buffer w/o having to call driver.

    set x [gets $f]
    close $f
    set x    
} $a
unset a
test io-8.5 {PeekAhead: don't peek if last read was short} {stdio testchannel openpipe fileevent} {
    # (bufPtr->nextAdded < bufPtr->length)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto binary}
    puts -nonewline $f "abcdefghijklmno\r"
    flush $f
    # here
    set x [list [gets $f line] $line [testchannel queuedcr $f]]
    close $f
    set x
} {15 abcdefghijklmno 1}
test io-8.6 {PeekAhead: change to non-blocking mode} {stdio testchannel openpipe fileevent} {
    # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0) 

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto binary} -buffersize 16
    puts -nonewline $f "abcdefghijklmno\r"
    flush $f
    # here
    set x [list [gets $f line] $line [testchannel queuedcr $f]]
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\n"
test io-13.3 {TranslateInputEOL: crlf mode: naked cr} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\r"
test io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\rfgh"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\rfgh"
test io-13.5 {TranslateInputEOL: crlf mode: naked lf} {
    # (src >= srcMax)

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\nfgh"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf







|












|












|







1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\n"
test io-13.3 {TranslateInputEOL: crlf mode: naked cr} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\r"
test io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\rfgh"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "abcd\ndef\rfgh"
test io-13.5 {TranslateInputEOL: crlf mode: naked lf} {
    # (src >= srcMax) 

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\r\ndef\nfgh"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation crlf
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
    set f [open $path(test1)]
    fconfigure $f -translation auto
    set x [read $f]
    close $f
    set x
} "abcd\ndef"
test io-13.10 {TranslateInputEOL: auto mode: \n} {
    # not (*src == '\r')

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\ndef"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto







|







1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
    set f [open $path(test1)]
    fconfigure $f -translation auto
    set x [read $f]
    close $f
    set x
} "abcd\ndef"
test io-13.10 {TranslateInputEOL: auto mode: \n} {
    # not (*src == '\r') 

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\ndef"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
    encoding system ascii
    set f [open $path(test1) w]
    set x [fconfigure $f -encoding]
    close $f
    encoding system $old
	close $a
    set x
} {ascii}
test io-20.2 {Tcl_CreateChannel: initial settings} {win} {
    set f [open $path(test1) w+]
    set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
    close $f
    set x
} [list [list \x1a ""] {auto crlf}]
test io-20.3 {Tcl_CreateChannel: initial settings} {unix} {







|







2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
    encoding system ascii
    set f [open $path(test1) w]
    set x [fconfigure $f -encoding]
    close $f
    encoding system $old
	close $a
    set x
} {ascii}    
test io-20.2 {Tcl_CreateChannel: initial settings} {win} {
    set f [open $path(test1) w+]
    set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
    close $f
    set x
} [list [list \x1a ""] {auto crlf}]
test io-20.3 {Tcl_CreateChannel: initial settings} {unix} {
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
test io-26.1 {Tcl_GetChannelInstanceData} {stdio openpipe} {
    # "pid" command uses Tcl_GetChannelInstanceData
    # Don't care what pid is (but must be a number), just want to exercise it.

    set f [open "|[list [interpreter] << exit]"]
    expr [pid $f]
    close $f
} {}

# Test flushing. The functions tested here are FlushChannel.

test io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    flush $f







|







2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
test io-26.1 {Tcl_GetChannelInstanceData} {stdio openpipe} {
    # "pid" command uses Tcl_GetChannelInstanceData
    # Don't care what pid is (but must be a number), just want to exercise it.

    set f [open "|[list [interpreter] << exit]"]
    expr [pid $f]
    close $f
} {}    

# Test flushing. The functions tested here are FlushChannel.

test io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    flush $f
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
    lappend l [file size $path(test1)]
    flush $f
    lappend l [file size $path(test1)]
    close $f
    set l
} {0 60 72}
test io-27.5 {FlushChannel, implicit flush when buffer fills and on close} \
	{unixOrWin} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffersize 60 -eofchar {}
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	puts $f hello
    }
    lappend l [file size $path(test1)]
    close $f
    lappend l [file size $path(test1)]
    set l
} {0 60 72}
set path(pipe)   [makeFile {} pipe]
set path(output) [makeFile {} output]
test io-27.6 {FlushChannel, async flushing, async close} \
	{stdio asyncPipeClose openpipe knownMsvcBug} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {







|
















|







2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
    lappend l [file size $path(test1)]
    flush $f
    lappend l [file size $path(test1)]
    close $f
    set l
} {0 60 72}
test io-27.5 {FlushChannel, implicit flush when buffer fills and on close} \
	{unixOrPc} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffersize 60 -eofchar {}
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	puts $f hello
    }
    lappend l [file size $path(test1)]
    close $f
    lappend l [file size $path(test1)]
    set l
} {0 60 72}
set path(pipe)   [makeFile {} pipe]
set path(output) [makeFile {} output]
test io-27.6 {FlushChannel, async flushing, async close} \
	{stdio asyncPipeClose openpipe} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
    # allow a little time for the background process to close.
    # otherwise, the following test fails on the [file delete $path(output)
    # on Windows because a process still has the file open.
    after 100 set v 1; vwait v
    set result
} ok
test io-29.32 {Tcl_WriteChars, background flush to slow reader} \
	{stdio asyncPipeClose openpipe knownMsvcBug} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {fconfigure $f -translation lf}







|







2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
    # allow a little time for the background process to close.
    # otherwise, the following test fails on the [file delete $path(output)
    # on Windows because a process still has the file open.
    after 100 set v 1; vwait v
    set result
} ok
test io-29.32 {Tcl_WriteChars, background flush to slow reader} \
	{stdio asyncPipeClose openpipe} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {fconfigure $f -translation lf}
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
    fconfigure $f -translation cr
    puts $f hello\nthere\nand\nhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x
} "hello\rthere\rand\rhere\r"
test io-30.7 {Tcl_Write crlf, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    puts $f hello\nthere\nand\nhere
    close $f







|







3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
    fconfigure $f -translation cr
    puts $f hello\nthere\nand\nhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf
    set x [read $f]
    close $f
    set x 
} "hello\rthere\rand\rhere\r"
test io-30.7 {Tcl_Write crlf, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    puts $f hello\nthere\nand\nhere
    close $f
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
    set line "123456789ABCDE"	;# 14 char plus crlf
    puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	puts $f $line
    }
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [expr 700*15+1]







|







3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
    set line "123456789ABCDE"	;# 14 char plus crlf
    puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	puts $f $line
    }
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf 
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [expr 700*15+1]
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
    set x [fconfigure $f -buffersize]
    close $f
    set x
} 40000
test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -encoding {}
    puts -nonewline $f \xe7\x89\xa6
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x







|







5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
    set x [fconfigure $f -buffersize]
    close $f
    set x
} 40000
test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -encoding {} 
    puts -nonewline $f \xe7\x89\xa6
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
    close $f1
    after 500
    set f [open $path(test1)]
    lappend result [read $f]
    close $f
    set result
} "ready line1 line2 {done\n}"
test io-53.4 {CopyData: background write overflow} {stdio openpipe fileevent fcopy} {
    set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
    variable x
    for {set x 0} {$x < 12} {incr x} {
	append big $big
    }
#    file delete $path(test1)
    file delete $path(pipe)







|







7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
    close $f1
    after 500
    set f [open $path(test1)]
    lappend result [read $f]
    close $f
    set result
} "ready line1 line2 {done\n}"
test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileevent fcopy} {
    set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
    variable x
    for {set x 0} {$x < 12} {incr x} {
	append big $big
    }
#    file delete $path(test1)
    file delete $path(pipe)
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
    chan copy $c $outChan
} -cleanup {
    close $outChan
    close $c
    removeFile out
} -result 100

test io-54.1 {Recursive channel events} {socket fileevent knownMsvcBug} {
    # This test checks to see if file events are delivered during recursive
    # event loops when there is buffered data on the channel.

    proc accept {s a p} {
	variable as
	fconfigure $s -translation lf
	puts $s "line 1\nline2\nline3"







|







7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
    chan copy $c $outChan
} -cleanup {
    close $outChan
    close $c
    removeFile out
} -result 100

test io-54.1 {Recursive channel events} {socket fileevent} {
    # This test checks to see if file events are delivered during recursive
    # event loops when there is buffered data on the channel.

    proc accept {s a p} {
	variable as
	fconfigure $s -translation lf
	puts $s "line 1\nline2\nline3"
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
    vwait [namespace which -variable result]
    close $s
    close $s2
    close $server
    set result
} {1 readable 234567890 timer}

test io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrWin openpipe fileevent} {
    set out [open $path(script) w]
    puts $out {
	puts "normal message from pipe"
	puts stderr "error message from pipe"
	exit 1
    }
    proc readit {pipe} {







|







8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
    vwait [namespace which -variable result]
    close $s
    close $s2
    close $server
    set result
} {1 readable 234567890 timer}

test io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrPc openpipe fileevent} {
    set out [open $path(script) w]
    puts $out {
	puts "normal message from pipe"
	puts stderr "error message from pipe"
	exit 1
    }
    proc readit {pipe} {
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
test io-74.1 {[104f2885bb] improper cache validity check} -setup {
    set fn [makeFile {} io-74.1]
    set rfd [open $fn r]
    testobj freeallvars
    interp create slave
} -constraints testobj -body {
    teststringobj set 1 [string range $rfd 0 end]
    read [teststringobj get 1]
    testobj duplicate 1 2
    interp transfer {} $rfd slave
    catch {read [teststringobj get 1]}
    read [teststringobj get 2]
} -cleanup {
    interp delete slave
    testobj freeallvars
    removeFile io-74.1
} -returnCodes error -match glob -result {can not find channel named "*"}

# ### ### ### ######### ######### #########







|



|







8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
test io-74.1 {[104f2885bb] improper cache validity check} -setup {
    set fn [makeFile {} io-74.1]
    set rfd [open $fn r]
    testobj freeallvars
    interp create slave
} -constraints testobj -body {
    teststringobj set 1 [string range $rfd 0 end]
    read [teststringobj get 1]		
    testobj duplicate 1 2
    interp transfer {} $rfd slave
    catch {read [teststringobj get 1]}
    read [teststringobj get 2]		
} -cleanup {
    interp delete slave
    testobj freeallvars
    removeFile io-74.1
} -returnCodes error -match glob -result {can not find channel named "*"}

# ### ### ### ######### ######### #########

Changes to tests/ioCmd.test.

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    close $chan
    set res
} {1 {bad option "-buffer": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation}}
removeFile fconfigure.dummy
test iocmd-8.14 {fconfigure command} {
    fconfigure stdin -buffers
} 4096
test iocmd-8.15.1 {fconfigure command / tcp channel} -constraints {socket unixOrWin} -setup {
    set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
    set port [lindex [fconfigure $srv -sockname] 2]
    proc iocmdSRV {sock ip port} {close $sock}
    set cli [socket 127.0.0.1 $port]
} -body {
    fconfigure $cli -blah
} -cleanup {







|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    close $chan
    set res
} {1 {bad option "-buffer": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation}}
removeFile fconfigure.dummy
test iocmd-8.14 {fconfigure command} {
    fconfigure stdin -buffers
} 4096
test iocmd-8.15.1 {fconfigure command / tcp channel} -constraints {socket unixOrPc} -setup {
    set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
    set port [lindex [fconfigure $srv -sockname] 2]
    proc iocmdSRV {sock ip port} {close $sock}
    set cli [socket 127.0.0.1 $port]
} -body {
    fconfigure $cli -blah
} -cleanup {
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
test iocmd-10.5 {fblocked command} {
    fblocked stdin
} 0

set path(test4) [makeFile {} test4]
set path(test5) [makeFile {} test5]

test iocmd-11.1 {I/O to command pipelines} {unixOrWin unixExecs} {
    set f [open $path(test4) w]
    close $f
    list [catch {open "| cat < \"$path(test4)\" > \"$path(test5)\"" w} msg] $msg $::errorCode
} {1 {can't write input to command: standard input was redirected} NONE}
test iocmd-11.2 {I/O to command pipelines} {unixOrWin unixExecs} {
    list [catch {open "| echo > \"$path(test5)\"" r} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
test iocmd-11.3 {I/O to command pipelines} {unixOrWin unixExecs} {
    list [catch {open "| echo > \"$path(test5)\"" r+} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
test iocmd-11.4 {I/O to command pipelines} unixOrWin {
    list [catch {open "| no_such_command_exists" rb} msg] $msg $::errorCode
} {1 {couldn't execute "no_such_command_exists": no such file or directory} {POSIX ENOENT {no such file or directory}}}

test iocmd-12.1 {POSIX open access modes: RDONLY} {
    file delete $path(test1)
    set f [open $path(test1) w]
    puts $f "Two lines: this one"







|




|


|


|







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
test iocmd-10.5 {fblocked command} {
    fblocked stdin
} 0

set path(test4) [makeFile {} test4]
set path(test5) [makeFile {} test5]

test iocmd-11.1 {I/O to command pipelines} {unixOrPc unixExecs} {
    set f [open $path(test4) w]
    close $f
    list [catch {open "| cat < \"$path(test4)\" > \"$path(test5)\"" w} msg] $msg $::errorCode
} {1 {can't write input to command: standard input was redirected} NONE}
test iocmd-11.2 {I/O to command pipelines} {unixOrPc unixExecs} {
    list [catch {open "| echo > \"$path(test5)\"" r} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
test iocmd-11.3 {I/O to command pipelines} {unixOrPc unixExecs} {
    list [catch {open "| echo > \"$path(test5)\"" r+} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
test iocmd-11.4 {I/O to command pipelines} unixOrPc {
    list [catch {open "| no_such_command_exists" rb} msg] $msg $::errorCode
} {1 {couldn't execute "no_such_command_exists": no such file or directory} {POSIX ENOENT {no such file or directory}}}

test iocmd-12.1 {POSIX open access modes: RDONLY} {
    file delete $path(test1)
    set f [open $path(test1) w]
    puts $f "Two lines: this one"
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
		    configure cget cgetall}
	} finalize {
	    return
	}
    }
    set ch [chan create {read write} foo]
} -body {
    chan configure $ch -blocking 0
} -cleanup {
    close $ch
    rename foo {}
} -match glob -returnCodes 1 -result {*(infinite loop?)*}
test iocmd-21.21 {[close] in [read] segfaults} -setup {
    proc foo {method chan args} {
	switch -- $method initialize {
	    return {initialize finalize watch read}
	} finalize {} watch {} read {
	    close $chan
	    return a







|



|







764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
		    configure cget cgetall}
	} finalize {
	    return
	}
    }
    set ch [chan create {read write} foo]
} -body {
    list [catch {chan configure $ch -blocking 0} m] $m
} -cleanup {
    close $ch
    rename foo {}
} -match glob -result {1 {*nested eval*}}
test iocmd-21.21 {[close] in [read] segfaults} -setup {
    proc foo {method chan args} {
	switch -- $method initialize {
	    return {initialize finalize watch read}
	} finalize {} watch {} read {
	    close $chan
	    return a
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
    set res
} -result {{unmatched open brace in list}}
test iocmd-31.6 {chan postevent, posted events do happen} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; return}
    set c [chan create {r w} foo]
    note [fileevent $c readable {note TOCK}]
    set stop [after 15000 {note TIMEOUT}]
    after  1000 {note [chan postevent $c r]}
    vwait ::res
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; return}
    set c [chan create {r w} foo]
    note [fileevent $c writable {note TOCK}]
    set stop [after 15000 {note TIMEOUT}]
    after  1000 {note [chan postevent $c w]}
    vwait ::res
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}







|












|







1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
    set res
} -result {{unmatched open brace in list}}
test iocmd-31.6 {chan postevent, posted events do happen} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; return}
    set c [chan create {r w} foo]
    note [fileevent $c readable {note TOCK}]
    set stop [after 10000 {note TIMEOUT}]
    after  1000 {note [chan postevent $c r]}
    vwait ::res
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; return}
    set c [chan create {r w} foo]
    note [fileevent $c writable {note TOCK}]
    set stop [after 10000 {note TIMEOUT}]
    after  1000 {note [chan postevent $c w]}
    vwait ::res
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}

Changes to tests/link.test.

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
}

testConstraint testlink [llength [info commands testlink]]

foreach i {int real bool string} {
    catch {unset $i}
}

test link-0.1 {leak test} {testlink} {
    interp create i
    load {} Tcltest i
    i eval {
	testlink create 1 0 0 0 0 0 0 0 0 0 0 0 0 0
	namespace delete ::
    }
    interp delete i
} {}

test link-1.1 {reading C variables from Tcl} {testlink} {
    testlink delete
    testlink set 43 1.23 4 - 12341234 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
    testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    list $int $real $bool $string $wide
} {43 1.23 1 NULL 12341234}
test link-1.2 {reading C variables from Tcl} {testlink} {







<
<
<
<
<
<
<
<
<
<
<







17
18
19
20
21
22
23











24
25
26
27
28
29
30
}

testConstraint testlink [llength [info commands testlink]]

foreach i {int real bool string} {
    catch {unset $i}
}











test link-1.1 {reading C variables from Tcl} {testlink} {
    testlink delete
    testlink set 43 1.23 4 - 12341234 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
    testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    list $int $real $bool $string $wide
} {43 1.23 1 NULL 12341234}
test link-1.2 {reading C variables from Tcl} {testlink} {

Changes to tests/list.test.

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
test list-3.1 {SetListFromAny and lrange/concat results} {
    slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}

test list-4.1 {Bug 3173086} {
    string is list "{[list \\\\\}]}"
} 1
test list-4.2 {Bug 35a8f1c04a, check correct str-rep} {
    set result {}
    foreach i {
	{#"} {#"""} {#"""""""""""""""}
	"#\"{" "#\"\"\"{" "#\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\{"
	"#\"}" "#\"\"\"}" "#\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\}"
    } {
	set list [list $i]
	set list [string trim " $list "]
	if {[llength $list] > 1 || $i ne [lindex $list 0]} {
	    lappend result "wrong string-representation of list by '$i', length: [llength $list], list: '$list'"
	}
    }
    set result [join $result \n]
} {}
test list-4.3 {Bug 35a8f1c04a, check correct string length} {
    string length [list #""]
} 5

# cleanup
::tcltest::cleanupTests
return







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




104
105
106
107
108
109
110


















111
112
113
114
test list-3.1 {SetListFromAny and lrange/concat results} {
    slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}

test list-4.1 {Bug 3173086} {
    string is list "{[list \\\\\}]}"
} 1



















# cleanup
::tcltest::cleanupTests
return

Changes to tests/load.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Commands covered:  load
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Commands covered:  load
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
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
120
121
122
123
124
125
126
127
128
129
130
131
	[list $dll $loaded] {
    load [file join $testDir pkga$ext]
    list [pkga_eq abc def] [info commands pkga_*]
} {0 {pkga_eq pkga_quote}}
interp create -safe child
test load-2.2 {loading into a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    load [file join $testDir pkgb$ext] Pkgb child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
	    [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test load-2.3 {loading with no _Init procedure} -constraints [list $dll $loaded] \
-body {
    list [catch {load [file join $testDir pkgc$ext] Foo} msg] $msg
} -match glob -result {1 {*couldn't find procedure Foo_Init}}
test load-2.4 {loading with no _SafeInit procedure} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] {} child} msg] $msg
} {1 {can't use package in a safe interpreter: no Pkga_SafeInit procedure}}

test load-3.1 {error in _Init procedure, same interpreter} \
	[list $dll $loaded] {
    list [catch {load [file join $testDir pkge$ext] Pkge} msg] \
	    $msg $::errorInfo $::errorCode
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] Pkge"} {POSIX ENOENT {no such file or directory}}}
test load-3.2 {error in _Init procedure, slave interpreter} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
    set ::errorCode foo
    set ::errorInfo bar
    set result [list [catch {load [file join $testDir pkge$ext] Pkge x} msg] \
	    $msg $::errorInfo $::errorCode]
    interp delete x
    set result
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] Pkge x"} {POSIX ENOENT {no such file or directory}}}

test load-4.1 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] Pkga} msg] $msg
} {0 {}}
test load-4.2 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] Pkgb} msg] $msg
} [list 1 "file \"[file join $testDir pkga$ext]\" is already loaded for package \"Pkga\""]

test load-5.1 {file name not specified and no static package: pick default} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
    load [file join $testDir pkga$ext] Pkga
    load {} pkga x
    set result [info loaded x]
    interp delete x
    set result
} [list [list [file join $testDir pkga$ext] Pkga]]

# On some platforms, like SunOS 4.1.3, these tests can't be run because







|





|







|







|






|









|


|


|






|







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
120
121
122
123
124
125
126
127
128
129
130
131
	[list $dll $loaded] {
    load [file join $testDir pkga$ext]
    list [pkga_eq abc def] [info commands pkga_*]
} {0 {pkga_eq pkga_quote}}
interp create -safe child
test load-2.2 {loading into a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    load [file join $testDir pkgb$ext] pKgB child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
	    [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test load-2.3 {loading with no _Init procedure} -constraints [list $dll $loaded] \
-body {
    list [catch {load [file join $testDir pkgc$ext] foo} msg] $msg
} -match glob -result {1 {*couldn't find procedure Foo_Init}}
test load-2.4 {loading with no _SafeInit procedure} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] {} child} msg] $msg
} {1 {can't use package in a safe interpreter: no Pkga_SafeInit procedure}}

test load-3.1 {error in _Init procedure, same interpreter} \
	[list $dll $loaded] {
    list [catch {load [file join $testDir pkge$ext] pkge} msg] \
	    $msg $::errorInfo $::errorCode
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] pkge"} {POSIX ENOENT {no such file or directory}}}
test load-3.2 {error in _Init procedure, slave interpreter} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
    set ::errorCode foo
    set ::errorInfo bar
    set result [list [catch {load [file join $testDir pkge$ext] pkge x} msg] \
	    $msg $::errorInfo $::errorCode]
    interp delete x
    set result
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] pkge x"} {POSIX ENOENT {no such file or directory}}}

test load-4.1 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] pkga} msg] $msg
} {0 {}}
test load-4.2 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] pkgb} msg] $msg
} [list 1 "file \"[file join $testDir pkga$ext]\" is already loaded for package \"Pkga\""]

test load-5.1 {file name not specified and no static package: pick default} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
    load [file join $testDir pkga$ext] pkga
    load {} pkga x
    set result [info loaded x]
    interp delete x
    set result
} [list [list [file join $testDir pkga$ext] Pkga]]

# On some platforms, like SunOS 4.1.3, these tests can't be run because
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
test load-8.2 {TclGetLoadedPackages procedure} [list teststaticpkg] {
    list [catch {info loaded gorp} msg] $msg
} {1 {could not find interpreter "gorp"}}
test load-8.3 {TclGetLoadedPackages procedure} [list teststaticpkg $dll $loaded] {
    list [info loaded {}] [info loaded child]
} [list [concat [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]]
test load-8.4 {TclGetLoadedPackages procedure} [list $dll $loaded teststaticpkg] {
    load [file join $testDir pkgb$ext] Pkgb
    list [info loaded {}] [lsort [info commands pkgb_*]]
} [list [concat [list [list [file join $testDir pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] {pkgb_sub pkgb_unsafe}]
interp delete child

test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} \
    -constraints {teststaticpkg} \
    -setup {







|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
test load-8.2 {TclGetLoadedPackages procedure} [list teststaticpkg] {
    list [catch {info loaded gorp} msg] $msg
} {1 {could not find interpreter "gorp"}}
test load-8.3 {TclGetLoadedPackages procedure} [list teststaticpkg $dll $loaded] {
    list [info loaded {}] [info loaded child]
} [list [concat [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]]
test load-8.4 {TclGetLoadedPackages procedure} [list $dll $loaded teststaticpkg] {
    load [file join $testDir pkgb$ext] pkgb
    list [info loaded {}] [lsort [info commands pkgb_*]]
} [list [concat [list [list [file join $testDir pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] {pkgb_sub pkgb_unsafe}]
interp delete child

test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} \
    -constraints {teststaticpkg} \
    -setup {

Changes to tests/macOSXFCmd.test.

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
test macOSXFCmd-2.6 {MacOSXSetFileAttribute - hidden} {macosxFileAttr notRoot} {
    catch {file delete -force -- foo.test}
    close [open foo.test w]
    list [catch {file attributes foo.test -hidden 1} msg] $msg \
	    [catch {file attributes foo.test -hidden} msg] $msg \
	    [file delete -force -- foo.test]
} {0 {} 0 1 {}}
test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot nonPortable} {
    catch {file delete -force -- foo.test}
    close [open foo.test w]
    catch {
	set f [open foo.test/..namedfork/rsrc w]
	fconfigure $f -translation lf -eofchar {}
	puts -nonewline $f "foo"
	close $f







|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
test macOSXFCmd-2.6 {MacOSXSetFileAttribute - hidden} {macosxFileAttr notRoot} {
    catch {file delete -force -- foo.test}
    close [open foo.test w]
    list [catch {file attributes foo.test -hidden 1} msg] $msg \
	    [catch {file attributes foo.test -hidden} msg] $msg \
	    [file delete -force -- foo.test]
} {0 {} 0 1 {}}
test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot} {
    catch {file delete -force -- foo.test}
    close [open foo.test w]
    catch {
	set f [open foo.test/..namedfork/rsrc w]
	fconfigure $f -translation lf -eofchar {}
	puts -nonewline $f "foo"
	close $f
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	file attributes baz.test -creator FOOC -type FOOT
	file attributes foo.test -creator FOOC
	file attributes inv.test -hidden 1
	file attributes inw.test -hidden 1 -type FOOT
	file attributes dir.test -hidden 1
    }
    set res [list \
	    [catch {lsort [glob *.test]} msg] $msg \
	    [catch {lsort [glob -types FOOT *.test]} msg] $msg \
	    [catch {lsort [glob -types {{macintosh type FOOT}} *.test]} msg] $msg \
	    [catch {lsort [glob -types FOOTT *.test]} msg] $msg \
	    [catch {lsort [glob -types {{macintosh type FOOTT}} *.test]} msg] $msg \
	    [catch {lsort [glob -types {{macintosh type {}}} *.test]} msg] $msg \
	    [catch {lsort [glob -types {{macintosh creator FOOC}} *.test]} msg] $msg \
	    [catch {lsort [glob -types {{macintosh creator FOOC} {macintosh type FOOT}} *.test]} msg] $msg \
	    [catch {lsort [glob -types hidden *.test]} msg] $msg \
	    [catch {lsort [glob -types {hidden FOOT} *.test]} msg] $msg \
	]
    cd ..
    file delete -force globtest
    set res
} [list \
	0 {bar.test baz.test dir.test foo.test inv.test inw.test reg.test} \
	0 {bar.test baz.test inw.test} 0 {bar.test baz.test inw.test} \







|
|
|
|
|
|
|
|
|
|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	file attributes baz.test -creator FOOC -type FOOT
	file attributes foo.test -creator FOOC
	file attributes inv.test -hidden 1
	file attributes inw.test -hidden 1 -type FOOT
	file attributes dir.test -hidden 1
    }
    set res [list \
	    [catch {glob *.test} msg] $msg \
	    [catch {glob -types FOOT *.test} msg] $msg \
	    [catch {glob -types {{macintosh type FOOT}} *.test} msg] $msg \
	    [catch {glob -types FOOTT *.test} msg] $msg \
	    [catch {glob -types {{macintosh type FOOTT}} *.test} msg] $msg \
	    [catch {glob -types {{macintosh type {}}} *.test} msg] $msg \
	    [catch {glob -types {{macintosh creator FOOC}} *.test} msg] $msg \
	    [catch {glob -types {{macintosh creator FOOC} {macintosh type FOOT}} *.test} msg] $msg \
	    [catch {glob -types hidden *.test} msg] $msg \
	    [catch {glob -types {hidden FOOT} *.test} msg] $msg \
	]
    cd ..
    file delete -force globtest
    set res
} [list \
	0 {bar.test baz.test dir.test foo.test inv.test inw.test reg.test} \
	0 {bar.test baz.test inw.test} 0 {bar.test baz.test inw.test} \

Changes to tests/main.test.

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] 0]\n

    test Tcl_Main-1.5 {
	Tcl_Main: encoding of script name: system encoding loss
	Note the shortcoming explained in Tcl Feature Request 491789
    } -constraints {
	stdio tempNotWin
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u00c0
	catch {set f [open "|[list [interpreter] \u00c0]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f







|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] 0]\n

    test Tcl_Main-1.5 {
	Tcl_Main: encoding of script name: system encoding loss
	Note the shortcoming explained in Tcl Feature Request 491789
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u00c0
	catch {set f [open "|[list [interpreter] \u00c0]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	catch {chan configure $f -blocking 0}
    } -body {
	type $f "chan configure stdin -eofchar \\032
	    if 1 \{\n\032"
	variable wait
	chan event $f readable \
		[list set [namespace which -variable wait] "child exit"]
	set id [after 5000 [list set [namespace which -variable wait] timeout]]
	vwait [namespace which -variable wait]
	after cancel $id
	set wait
    } -cleanup {
	if {$wait eq "timeout" && [testConstraint unix]} {
	    exec kill [pid $f]
	}







|







617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	catch {chan configure $f -blocking 0}
    } -body {
	type $f "chan configure stdin -eofchar \\032
	    if 1 \{\n\032"
	variable wait
	chan event $f readable \
		[list set [namespace which -variable wait] "child exit"]
	set id [after 2000 [list set [namespace which -variable wait] timeout]]
	vwait [namespace which -variable wait]
	after cancel $id
	set wait
    } -cleanup {
	if {$wait eq "timeout" && [testConstraint unix]} {
	    exec kill [pid $f]
	}
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
	set cmd {makeFile "if 1 \{" script}
	catch {set f [open "|[list [interpreter]] < [list [eval $cmd]]" r]}
	catch {chan configure $f -blocking 0}
    } -body {
	variable wait
	chan event $f readable \
		[list set [namespace which -variable wait] "child exit"]
	set id [after 5000 [list set [namespace which -variable wait] timeout]]
	vwait [namespace which -variable wait]
	after cancel $id
	set wait
    } -cleanup {
	if {$wait eq "timeout" && [testConstraint unix]} {
	    exec kill [pid $f]
	}







|







640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
	set cmd {makeFile "if 1 \{" script}
	catch {set f [open "|[list [interpreter]] < [list [eval $cmd]]" r]}
	catch {chan configure $f -blocking 0}
    } -body {
	variable wait
	chan event $f readable \
		[list set [namespace which -variable wait] "child exit"]
	set id [after 2000 [list set [namespace which -variable wait] timeout]]
	vwait [namespace which -variable wait]
	after cancel $id
	set wait
    } -cleanup {
	if {$wait eq "timeout" && [testConstraint unix]} {
	    exec kill [pid $f]
	}

Changes to tests/namespace.test.

2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
	return global
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1} {global,global,global,:: ::test_ns_1}" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
    catch {rename ::pathtestC {}}
}
test namespace-51.7 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
    }
    namespace eval ::test_ns_2 {
	namespace path ::test_ns_1
	proc getpath {} {namespace path}







<







2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
	return global
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1} {global,global,global,:: ::test_ns_1}" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}

}
test namespace-51.7 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
    }
    namespace eval ::test_ns_2 {
	namespace path ::test_ns_1
	proc getpath {} {namespace path}

Changes to tests/opt.test.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

test opt-6.1 {OptKeyParse} {
    ::tcl::OptKeyRegister {} test;
    list [catch {::tcl::OptKeyParse test {-help}} msg] $msg
} {1 {Usage information:
    Var/FlagName Type Value Help
    ------------ ---- ----- ----
    (-help                  gives this help)}}

test opt-7.1 {OptCheckType} {
    list \
	    [::tcl::OptCheckType 23 int] \
	    [::tcl::OptCheckType 23 float] \
	    [::tcl::OptCheckType true boolean] \
	    [::tcl::OptCheckType "-blah" any] \







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

test opt-6.1 {OptKeyParse} {
    ::tcl::OptKeyRegister {} test;
    list [catch {::tcl::OptKeyParse test {-help}} msg] $msg
} {1 {Usage information:
    Var/FlagName Type Value Help
    ------------ ---- ----- ----
    ( -help                 gives this help )}}

test opt-7.1 {OptCheckType} {
    list \
	    [::tcl::OptCheckType 23 int] \
	    [::tcl::OptCheckType 23 float] \
	    [::tcl::OptCheckType true boolean] \
	    [::tcl::OptCheckType "-blah" any] \
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#### behaviour tests #####

test opt-10.1 {ambigous flags} {
    ::tcl::OptProc optTest {{-fla} {-other} {-flag2xyz} {-flag3xyz}} {}
    catch {optTest -fL} msg
    set msg
} {ambigous option "-fL", choose from:
    -fla      boolflag (false)
    -flag2xyz boolflag (false)
    -flag3xyz boolflag (false)}
test opt-10.2 {non ambigous flags} {
    ::tcl::OptProc optTest {{-flag1xyz} {-other} {-flag2xyz} {-flag3xyz}} {
	return $flag2xyz
    }
    optTest -fLaG2
} 1
test opt-10.3 {non ambigous flags because of exact match} {
    ::tcl::OptProc optTest {{-flag1x} {-other} {-flag1} {-flag1xy}} {
	return $flag1
    }
    optTest -flAg1
} 1
test opt-10.4 {ambigous flags, not exact match} {
    ::tcl::OptProc optTest {{-flag1xy} {-other} {-flag1} {-flag1xyz}} {
	return $flag1
    }
    catch {optTest -fLag1X} msg
    set msg
} {ambigous option "-fLag1X", choose from:
    -flag1xy  boolflag (false)
    -flag1xyz boolflag (false)}

# medium size overall test example: (defined once)
::tcl::OptProc optTest {
    {cmd -choice {print save delete} "sub command to choose"}
    {-allowBoing -boolean true}
    {arg2 -string "this is help"}
    {?arg3? 7 "optional number"}







|
|
|



















|
|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#### behaviour tests #####

test opt-10.1 {ambigous flags} {
    ::tcl::OptProc optTest {{-fla} {-other} {-flag2xyz} {-flag3xyz}} {}
    catch {optTest -fL} msg
    set msg
} {ambigous option "-fL", choose from:
    -fla      boolflag (false) 
    -flag2xyz boolflag (false) 
    -flag3xyz boolflag (false) }
test opt-10.2 {non ambigous flags} {
    ::tcl::OptProc optTest {{-flag1xyz} {-other} {-flag2xyz} {-flag3xyz}} {
	return $flag2xyz
    }
    optTest -fLaG2
} 1
test opt-10.3 {non ambigous flags because of exact match} {
    ::tcl::OptProc optTest {{-flag1x} {-other} {-flag1} {-flag1xy}} {
	return $flag1
    }
    optTest -flAg1
} 1
test opt-10.4 {ambigous flags, not exact match} {
    ::tcl::OptProc optTest {{-flag1xy} {-other} {-flag1} {-flag1xyz}} {
	return $flag1
    }
    catch {optTest -fLag1X} msg
    set msg
} {ambigous option "-fLag1X", choose from:
    -flag1xy  boolflag (false) 
    -flag1xyz boolflag (false) }

# medium size overall test example: (defined once)
::tcl::OptProc optTest {
    {cmd -choice {print save delete} "sub command to choose"}
    {-allowBoing -boolean true}
    {arg2 -string "this is help"}
    {?arg3? 7 "optional number"}
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
} {1 {no value given for parameter "cmd" (use -help for full usage) :
    cmd choice (print save delete) sub command to choose}}
test opt-10.6 {medium size overall test} {
    list [catch {optTest -help} msg] $msg
} {1 {Usage information:
    Var/FlagName Type     Value   Help
    ------------ ----     -----   ----
    (-help                        gives this help)
    cmd          choice   (print save delete) sub command to choose
    -allowBoing  boolean  (true)
    arg2         string   ()      this is help
    ?arg3?       int      (7)     optional number
    -moreflags   boolflag (false)}}
test opt-10.7 {medium size overall test} {
    optTest save tst
} {save 1 tst 7 0}
test opt-10.8 {medium size overall test} {
    optTest save -allowBoing false -- 8
} {save 0 8 7 0}
test opt-10.9 {medium size overall test} {
    optTest save tst -m --
} {save 1 tst 7 1}
test opt-10.10 {medium size overall test} {
    list [catch {optTest save tst foo} msg] [lindex [split $msg "\n"] 0]
} {1 {too many arguments (unexpected argument(s): foo), usage:}}

test opt-11.1 {too many args test 2} {
    set key [::tcl::OptKeyRegister {-foo}]
    list [catch {::tcl::OptKeyParse $key {-foo blah}} msg] $msg\
	    [::tcl::OptKeyDelete $key]
} {1 {too many arguments (unexpected argument(s): blah), usage:
    Var/FlagName Type     Value   Help
    ------------ ----     -----   ----
    (-help                        gives this help)
    -foo         boolflag (false)} {}}
test opt-11.2 {default value for args} {
    set args {}
    set key [::tcl::OptKeyRegister {{args -list {a b c} "args..."}}]
    ::tcl::OptKeyParse $key {}
    ::tcl::OptKeyDelete $key
    set args
} {a b c}

# cleanup
::tcltest::cleanupTests
return







|

|


|




















|
|











200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
} {1 {no value given for parameter "cmd" (use -help for full usage) :
    cmd choice (print save delete) sub command to choose}}
test opt-10.6 {medium size overall test} {
    list [catch {optTest -help} msg] $msg
} {1 {Usage information:
    Var/FlagName Type     Value   Help
    ------------ ----     -----   ----
    ( -help                       gives this help )
    cmd          choice   (print save delete) sub command to choose
    -allowBoing  boolean  (true)  
    arg2         string   ()      this is help
    ?arg3?       int      (7)     optional number
    -moreflags   boolflag (false) }}
test opt-10.7 {medium size overall test} {
    optTest save tst
} {save 1 tst 7 0}
test opt-10.8 {medium size overall test} {
    optTest save -allowBoing false -- 8
} {save 0 8 7 0}
test opt-10.9 {medium size overall test} {
    optTest save tst -m --
} {save 1 tst 7 1}
test opt-10.10 {medium size overall test} {
    list [catch {optTest save tst foo} msg] [lindex [split $msg "\n"] 0]
} {1 {too many arguments (unexpected argument(s): foo), usage:}}

test opt-11.1 {too many args test 2} {
    set key [::tcl::OptKeyRegister {-foo}]
    list [catch {::tcl::OptKeyParse $key {-foo blah}} msg] $msg\
	    [::tcl::OptKeyDelete $key]
} {1 {too many arguments (unexpected argument(s): blah), usage:
    Var/FlagName Type     Value   Help
    ------------ ----     -----   ----
    ( -help                       gives this help )
    -foo         boolflag (false) } {}}
test opt-11.2 {default value for args} {
    set args {}
    set key [::tcl::OptKeyRegister {{args -list {a b c} "args..."}}]
    ::tcl::OptKeyParse $key {}
    ::tcl::OptKeyDelete $key
    set args
} {a b c}

# cleanup
::tcltest::cleanupTests
return

Changes to tests/parse.test.

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
    info complete "# Comment should be complete command"
} 1
test parse-15.58 {CommandComplete procedure, memory leaks} {
    info complete "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22"
} 1
test parse-15.59 {CommandComplete procedure} {
    # Test for Tcl Bug 684744
    info complete [bytestring "\x00;if 1 \{"]
} 0
test parse-15.60 {CommandComplete procedure} {
    # Test for Tcl Bug 1968882
    info complete \\\n
} 0

test parse-16.1 {Tcl_EvalEx, check termOffset is set correctly for non TCL_OK cases, bug 2535} {







|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
    info complete "# Comment should be complete command"
} 1
test parse-15.58 {CommandComplete procedure, memory leaks} {
    info complete "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22"
} 1
test parse-15.59 {CommandComplete procedure} {
    # Test for Tcl Bug 684744
    info complete [encoding convertfrom identity "\x00;if 1 \{"]
} 0
test parse-15.60 {CommandComplete procedure} {
    # Test for Tcl Bug 1968882
    info complete \\\n
} 0

test parse-16.1 {Tcl_EvalEx, check termOffset is set correctly for non TCL_OK cases, bug 2535} {

Changes to tests/parseOld.test.

446
447
448
449
450
451
452


































































453
454
455
456
457
458
459

test parseOld-13.1 {comments at the end of a bracketed script} {
    set x "[
expr 1+1
# skip this!
]"
} {2}



































































test parseOld-15.1 {TclScriptEnd procedure} {
    info complete {puts [
	expr 1+1
	#this is a comment ]}
} {0}
test parseOld-15.2 {TclScriptEnd procedure} {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525

test parseOld-13.1 {comments at the end of a bracketed script} {
    set x "[
expr 1+1
# skip this!
]"
} {2}

test parseOld-14.1 {TclWordEnd procedure} {testwordend} {
    testwordend " 	\n abc"
} {c}
test parseOld-14.2 {TclWordEnd procedure} {testwordend} {
    testwordend "   \\\n"
} {}
test parseOld-14.3 {TclWordEnd procedure} {testwordend} {
    testwordend "   \\\n "
} { }
test parseOld-14.4 {TclWordEnd procedure} {testwordend} {
    testwordend {"abc"}
} {"}
#" Emacs formatting :^(
test parseOld-14.5 {TclWordEnd procedure} {testwordend} {
    testwordend {{xyz}}
} \}
test parseOld-14.6 {TclWordEnd procedure} {testwordend} {
    testwordend {{a{}b{}\}} xyz}
} "\} xyz"
test parseOld-14.7 {TclWordEnd procedure} {testwordend} {
    testwordend {abc[this is a]def ghi}
} {f ghi}
test parseOld-14.8 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n\n  "
} "s\\\n\n  "
test parseOld-14.9 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n   	"
} "s\\\n   	"
test parseOld-14.10 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n   	xyz"
} "s\\\n   	xyz"
test parseOld-14.11 {TclWordEnd procedure} {testwordend} {
    testwordend {a$x.$y(a long index) foo}
} ") foo"
test parseOld-14.12 {TclWordEnd procedure} {testwordend} {
    testwordend {abc; def}
} {; def}
test parseOld-14.13 {TclWordEnd procedure} {testwordend} {
    testwordend {abc def}
} {c def}
test parseOld-14.14 {TclWordEnd procedure} {testwordend} {
    testwordend {abc	def}
} {c	def}
test parseOld-14.15 {TclWordEnd procedure} {testwordend} {
    testwordend "abc\ndef"
} "c\ndef"
test parseOld-14.16 {TclWordEnd procedure} {testwordend} {
    testwordend "abc"
} {c}
test parseOld-14.17 {TclWordEnd procedure} {testwordend} {
    testwordend "a\000bc"
} {c}
test parseOld-14.18 {TclWordEnd procedure} {testwordend} {
    testwordend \[a\000\]
} {]}
test parseOld-14.19 {TclWordEnd procedure} {testwordend} {
    testwordend \"a\000\"
} {"}
#" Emacs formatting :^(
test parseOld-14.20 {TclWordEnd procedure} {testwordend} {
    testwordend a{\000}b
} {b}
test parseOld-14.21 {TclWordEnd procedure} {testwordend} {
    testwordend "   \000b"
} {b}

test parseOld-15.1 {TclScriptEnd procedure} {
    info complete {puts [
	expr 1+1
	#this is a comment ]}
} {0}
test parseOld-15.2 {TclScriptEnd procedure} {

Changes to tests/pid.test.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
}

testConstraint pidDefined [llength [info commands pid]]

test pid-1.1 {pid command} pidDefined {
    regexp {(^[0-9]+$)|(^0x[0-9a-fA-F]+$)} [pid]
} 1
test pid-1.2 {pid command} -constraints {unixOrWin unixExecs pidDefined} -setup {
    set path(test1) [makeFile {} test1]
    file delete $path(test1)
} -body {
    set f [open |[list echo foo | cat >$path(test1)] w]
    set pids [pid $f]
    close $f
    list [llength $pids] [regexp {^[0-9]+$} [lindex $pids 0]] \







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
}

testConstraint pidDefined [llength [info commands pid]]

test pid-1.1 {pid command} pidDefined {
    regexp {(^[0-9]+$)|(^0x[0-9a-fA-F]+$)} [pid]
} 1
test pid-1.2 {pid command} -constraints {unixOrPc unixExecs pidDefined} -setup {
    set path(test1) [makeFile {} test1]
    file delete $path(test1)
} -body {
    set f [open |[list echo foo | cat >$path(test1)] w]
    set pids [pid $f]
    close $f
    list [llength $pids] [regexp {^[0-9]+$} [lindex $pids 0]] \

Changes to tests/pkg.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.3.4
    namespace import -force ::tcltest::*
}

# Do all this in a child interp to avoid garbaging the
# package list
set i [interp create]
tcltest::loadIntoChildInterpreter $i {*}$argv

interp eval $i {
namespace import -force ::tcltest::*
package forget {*}[package names]
set oldPkgUnknown [package unknown]
package unknown {}
set oldPath $auto_path







|


|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.3.4
    namespace import -force ::tcltest::*
}

# Do all this in a slave interp to avoid garbaging the
# package list
set i [interp create]
tcltest::loadIntoSlaveInterpreter $i {*}$argv

interp eval $i {
namespace import -force ::tcltest::*
package forget {*}[package names]
set oldPkgUnknown [package unknown]
package unknown {}
set oldPath $auto_path

Changes to tests/pkgMkIndex.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# This file contains tests for the pkg_mkIndex command.
# Note that the tests are limited to Tcl scripts only, there are no shared
# libraries against which to test.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1998-1999 Scriptics Corporation.
# All rights reserved.

package require tcltest 2
namespace import ::tcltest::*

set fullPkgPath [makeDirectory pkg]








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# This file contains tests for the pkg_mkIndex command.
# Note that the tests are limited to Tcl scripts only, there are no shared
# libraries against which to test.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.

package require tcltest 2
namespace import ::tcltest::*

set fullPkgPath [makeDirectory pkg]

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
set x [file join [file dirname [info nameofexecutable]] dltest \
	pkga[info sharedlibextension]]
set dll "[file tail $x]Required"
testConstraint $dll [file exists $x]

if {[testConstraint $dll]} {
    makeFile {
#  This package provides pkga, which is also provided by a DLL.
package provide pkga 1.0
proc pkga_neq { x } {
    return [expr {! [pkgq_eq $x]}]
}
} [file join pkg pkga.tcl]
    file copy -force $x $fullPkgPath
}
testConstraint exec [llength [info commands ::exec]]

test pkgMkIndex-10.1 {package in DLL and script} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so 
    # we can delete the file and not get stuck because we're holding
    # a reference to it.
    set cmd [list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]
    exec [interpreter] << $cmd
    pkgtest::runCreatedIndex {0 {}} -lazy $fullPkgPath pkga[info sharedlibextension] pkga.tcl
} "0 {{pkga:1.0 {tclPkgSetup {pkga[info sharedlibextension] load {pkga_eq pkga_quote}} {pkga.tcl source pkga_neq}}}}"
test pkgMkIndex-10.2 {package in DLL hidden by -load} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so 
    # we can delete the file and not get stuck because we're holding
    # a reference to it.
    #
    # This test depends on context from prior test, so repeat it.
    set script "[list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]\n"







|
|















|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
set x [file join [file dirname [info nameofexecutable]] dltest \
	pkga[info sharedlibextension]]
set dll "[file tail $x]Required"
testConstraint $dll [file exists $x]

if {[testConstraint $dll]} {
    makeFile {
#  This package provides Pkga, which is also provided by a DLL.
package provide Pkga 1.0
proc pkga_neq { x } {
    return [expr {! [pkgq_eq $x]}]
}
} [file join pkg pkga.tcl]
    file copy -force $x $fullPkgPath
}
testConstraint exec [llength [info commands ::exec]]

test pkgMkIndex-10.1 {package in DLL and script} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so 
    # we can delete the file and not get stuck because we're holding
    # a reference to it.
    set cmd [list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]
    exec [interpreter] << $cmd
    pkgtest::runCreatedIndex {0 {}} -lazy $fullPkgPath pkga[info sharedlibextension] pkga.tcl
} "0 {{Pkga:1.0 {tclPkgSetup {pkga[info sharedlibextension] load {pkga_eq pkga_quote}} {pkga.tcl source pkga_neq}}}}"
test pkgMkIndex-10.2 {package in DLL hidden by -load} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so 
    # we can delete the file and not get stuck because we're holding
    # a reference to it.
    #
    # This test depends on context from prior test, so repeat it.
    set script "[list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]\n"

Changes to tests/reg.test.

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
    # This is near the limits of the RE engine
    regexp [string repeat x*y*z* 480] x
} 1

test reg-33.30 {Bug 1080042} {
    regexp {(\Y)+} foo
} 1
test reg-33.31 {Bug 7c64aa5e1a} {
    regexp -inline {(?b).\{1,10\}} {abcdef}
} abcdef



# cleanup
::tcltest::cleanupTests
return

# Local Variables:







<
<
<
<







1116
1117
1118
1119
1120
1121
1122




1123
1124
1125
1126
1127
1128
1129
    # This is near the limits of the RE engine
    regexp [string repeat x*y*z* 480] x
} 1

test reg-33.30 {Bug 1080042} {
    regexp {(\Y)+} foo
} 1






# cleanup
::tcltest::cleanupTests
return

# Local Variables:

Changes to tests/regexp.test.

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    set foo 2; set f2 2; set f3 2; set f4 2
    list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
} {1 {1 1} {1 1} {-1 -1} {-1 -1}}
test regexp-3.7 {getting substrings back from regexp} {
    set foo 1; set f2 1; set f3 1; set f4 1
    list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
} {1 {1 2} {1 1} {-1 -1} {2 2}}
test regexp-3.8a {-indices by multi-byte utf-8} {
    regexp -inline -indices {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"
} {{0 10} {0 3} {5 10}}
test regexp-3.8b {-indices by multi-byte utf-8, from -start position} {
    list\
	[regexp -inline -indices -start 3 {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"] \
	[regexp -inline -indices -start 4 {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"]
} {{{3 10} {3 3} {5 10}} {}}

test regexp-4.1 {-nocase option to regexp} {
    regexp -nocase foo abcFOo
} 1
test regexp-4.2 {-nocase option to regexp} {
    set f1 22
    set f2 33







<
<
<
<
<
<
<
<
<
<
<







152
153
154
155
156
157
158











159
160
161
162
163
164
165
    set foo 2; set f2 2; set f3 2; set f4 2
    list [regexp -indices (a)(b)? xay foo f2 f3 f4] $foo $f2 $f3 $f4
} {1 {1 1} {1 1} {-1 -1} {-1 -1}}
test regexp-3.7 {getting substrings back from regexp} {
    set foo 1; set f2 1; set f3 1; set f4 1
    list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
} {1 {1 2} {1 1} {-1 -1} {2 2}}












test regexp-4.1 {-nocase option to regexp} {
    regexp -nocase foo abcFOo
} 1
test regexp-4.2 {-nocase option to regexp} {
    set f1 22
    set f2 33

Changes to tests/registry.test.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    namespace import -force ::tcltest::*
}

testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::regver [package require registry 1.3.5]
	}]} {
	testConstraint reg 1
    }
}

# determine the current locale
testConstraint english [expr {
    [llength [info commands testlocale]]
    && [string match "English*" [testlocale all ""]]
}]

test registry-1.0 {check if we are testing the right dll} {win reg} {
    set ::regver
} {1.3.5}
test registry-1.1 {argument parsing for registry command} {win reg} {
    list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.2 {argument parsing for registry command} {win reg} {
    list [catch {registry foo} msg] $msg
} {1 {bad option "foo": must be broadcast, delete, get, keys, set, type, or values}}
test registry-1.2a {argument parsing for registry command} {win reg} {
    list [catch {registry -33bit foo} msg] $msg
} {1 {bad mode "-33bit": must be -32bit or -64bit}}

test registry-1.3 {argument parsing for registry command} {win reg} {
    list [catch {registry d} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
test registry-1.3a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit d} msg] $msg
} {1 {wrong # args: should be "registry -32bit delete keyName ?valueName?"}}
test registry-1.3b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit d} msg] $msg
} {1 {wrong # args: should be "registry -64bit delete keyName ?valueName?"}}
test registry-1.4 {argument parsing for registry command} {win reg} {
    list [catch {registry delete} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
test registry-1.5 {argument parsing for registry command} {win reg} {
    list [catch {registry delete foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}

test registry-1.6 {argument parsing for registry command} {win reg} {
    list [catch {registry g} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
test registry-1.6a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit g} msg] $msg
} {1 {wrong # args: should be "registry -32bit get keyName valueName"}}
test registry-1.6b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit g} msg] $msg
} {1 {wrong # args: should be "registry -64bit get keyName valueName"}}
test registry-1.7 {argument parsing for registry command} {win reg} {
    list [catch {registry get} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
test registry-1.8 {argument parsing for registry command} {win reg} {
    list [catch {registry get foo} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
test registry-1.9 {argument parsing for registry command} {win reg} {
    list [catch {registry get foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}

test registry-1.10 {argument parsing for registry command} {win reg} {
    list [catch {registry k} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
test registry-1.10a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit k} msg] $msg
} {1 {wrong # args: should be "registry -32bit keys keyName ?pattern?"}}
test registry-1.10b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit k} msg] $msg
} {1 {wrong # args: should be "registry -64bit keys keyName ?pattern?"}}
test registry-1.11 {argument parsing for registry command} {win reg} {
    list [catch {registry keys} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
test registry-1.12 {argument parsing for registry command} {win reg} {
    list [catch {registry keys foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}

test registry-1.13 {argument parsing for registry command} {win reg} {
    list [catch {registry s} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
test registry-1.13a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit s} msg] $msg
} {1 {wrong # args: should be "registry -32bit set keyName ?valueName data ?type??"}}
test registry-1.13b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit s} msg] $msg
} {1 {wrong # args: should be "registry -64bit set keyName ?valueName data ?type??"}}
test registry-1.14 {argument parsing for registry command} {win reg} {
    list [catch {registry set} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
test registry-1.15 {argument parsing for registry command} {win reg} {
    list [catch {registry set foo bar} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
test registry-1.16 {argument parsing for registry command} {win reg} {
    list [catch {registry set foo bar baz blat gorp} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}

test registry-1.17 {argument parsing for registry command} {win reg} {
    list [catch {registry t} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
test registry-1.17a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit t} msg] $msg
} {1 {wrong # args: should be "registry -32bit type keyName valueName"}}
test registry-1.17b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit t} msg] $msg
} {1 {wrong # args: should be "registry -64bit type keyName valueName"}}
test registry-1.18 {argument parsing for registry command} {win reg} {
    list [catch {registry type} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
test registry-1.19 {argument parsing for registry command} {win reg} {
    list [catch {registry type foo} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
test registry-1.20 {argument parsing for registry command} {win reg} {
    list [catch {registry type foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}

test registry-1.21 {argument parsing for registry command} {win reg} {
    list [catch {registry v} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
test registry-1.21a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit v} msg] $msg
} {1 {wrong # args: should be "registry -32bit values keyName ?pattern?"}}
test registry-1.21b {argument parsing for registry command} {win reg} {
    list [catch {registry -64bit v} msg] $msg
} {1 {wrong # args: should be "registry -64bit values keyName ?pattern?"}}
test registry-1.22 {argument parsing for registry command} {win reg} {
    list [catch {registry values} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
test registry-1.23 {argument parsing for registry command} {win reg} {
    list [catch {registry values foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}

test registry-2.1 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete foo} msg] $msg
} {1 {bad root name "foo": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-2.2 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete HKEY_CLASSES_ROOT} msg] $msg
} {1 {bad key: cannot delete root keys}}
test registry-2.3 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete HKEY_CLASSES_ROOT\\} msg] $msg
} {1 {bad key: cannot delete root keys}}
test registry-2.4 {DeleteKey: subkey at root level} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry keys HKEY_CURRENT_USER TclFoobar
} {}
test registry-2.5 {DeleteKey: subkey below root level} {win reg} {







|










|
<
<
<


|
<
<
<
<
<
<



<
<
<




<
<
<
<
<
<










<
<
<
<
<
<













<
<
<
<
<
<










<
<
<
<
<
<













<
<
<
<
<
<













<
<
<
<
<
<











|


|







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
120
121
122
123
124
    namespace import -force ::tcltest::*
}

testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    package require registry
	}]} {
	testConstraint reg 1
    }
}

# determine the current locale
testConstraint english [expr {
    [llength [info commands testlocale]]
    && [string match "English*" [testlocale all ""]]
}]




test registry-1.1 {argument parsing for registry command} {win reg} {
    list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry option ?arg arg ...?"}}






test registry-1.2 {argument parsing for registry command} {win reg} {
    list [catch {registry foo} msg] $msg
} {1 {bad option "foo": must be broadcast, delete, get, keys, set, type, or values}}




test registry-1.3 {argument parsing for registry command} {win reg} {
    list [catch {registry d} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}






test registry-1.4 {argument parsing for registry command} {win reg} {
    list [catch {registry delete} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
test registry-1.5 {argument parsing for registry command} {win reg} {
    list [catch {registry delete foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}

test registry-1.6 {argument parsing for registry command} {win reg} {
    list [catch {registry g} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}






test registry-1.7 {argument parsing for registry command} {win reg} {
    list [catch {registry get} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
test registry-1.8 {argument parsing for registry command} {win reg} {
    list [catch {registry get foo} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
test registry-1.9 {argument parsing for registry command} {win reg} {
    list [catch {registry get foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}

test registry-1.10 {argument parsing for registry command} {win reg} {
    list [catch {registry k} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}






test registry-1.11 {argument parsing for registry command} {win reg} {
    list [catch {registry keys} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
test registry-1.12 {argument parsing for registry command} {win reg} {
    list [catch {registry keys foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}

test registry-1.13 {argument parsing for registry command} {win reg} {
    list [catch {registry s} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}






test registry-1.14 {argument parsing for registry command} {win reg} {
    list [catch {registry set} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
test registry-1.15 {argument parsing for registry command} {win reg} {
    list [catch {registry set foo bar} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
test registry-1.16 {argument parsing for registry command} {win reg} {
    list [catch {registry set foo bar baz blat gorp} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}

test registry-1.17 {argument parsing for registry command} {win reg} {
    list [catch {registry t} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}






test registry-1.18 {argument parsing for registry command} {win reg} {
    list [catch {registry type} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
test registry-1.19 {argument parsing for registry command} {win reg} {
    list [catch {registry type foo} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
test registry-1.20 {argument parsing for registry command} {win reg} {
    list [catch {registry type foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}

test registry-1.21 {argument parsing for registry command} {win reg} {
    list [catch {registry v} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}






test registry-1.22 {argument parsing for registry command} {win reg} {
    list [catch {registry values} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
test registry-1.23 {argument parsing for registry command} {win reg} {
    list [catch {registry values foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}

test registry-2.1 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete foo} msg] $msg
} {1 {bad root name "foo": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-2.2 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete HKEY_CURRENT_USER} msg] $msg
} {1 {bad key: cannot delete root keys}}
test registry-2.3 {DeleteKey: bad key} {win reg} {
    list [catch {registry delete HKEY_CURRENT_USER\\} msg] $msg
} {1 {bad key: cannot delete root keys}}
test registry-2.4 {DeleteKey: subkey at root level} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry keys HKEY_CURRENT_USER TclFoobar
} {}
test registry-2.5 {DeleteKey: subkey below root level} {win reg} {
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u00c7bar
    registry set HKEY_CURRENT_USER\\TclFoobar\\blat
    registry set HKEY_CURRENT_USER\\TclFoobar\\foo
    set result [lsort [registry keys HKEY_CURRENT_USER\\TclFoobar b*]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "baz\u00c7bar blat"
test registry-4.8 {GetKeyNames: Unicode} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u30b7bar
    registry set HKEY_CURRENT_USER\\TclFoobar\\blat
    registry set HKEY_CURRENT_USER\\TclFoobar\\foo
    set result [lsort [registry keys HKEY_CURRENT_USER\\TclFoobar b*]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u00c7bar
    registry set HKEY_CURRENT_USER\\TclFoobar\\blat
    registry set HKEY_CURRENT_USER\\TclFoobar\\foo
    set result [lsort [registry keys HKEY_CURRENT_USER\\TclFoobar b*]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "baz\u00c7bar blat"
test registry-4.8 {GetKeyNames: Unicode} {win reg nt} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u30b7bar
    registry set HKEY_CURRENT_USER\\TclFoobar\\blat
    registry set HKEY_CURRENT_USER\\TclFoobar\\foo
    set result [lsort [registry keys HKEY_CURRENT_USER\\TclFoobar b*]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560
561

562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
} 1
test registry-6.17 {GetValue: Unicode value names} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar val\u00c71 foobar multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val\u00c71]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} foobar
test registry-6.18 {GetValue: values with Unicode strings} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u30b7r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba\u30b7r baz"
test registry-6.19 {GetValue: values with Unicode strings} {win reg english} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u00c7r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba\u00c7r baz"
test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u0000r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba r baz"
test registry-6.21 {GetValue: very long value names and values} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383] [string repeat x 16383] multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} [string repeat x 16383]

test registry-7.1 {GetValueNames: bad key} -constraints {win reg english} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry values HKEY_CURRENT_USER\\TclFoobar
} -returnCodes error -result {unable to open key: The system cannot find the file specified.}
test registry-7.2 {GetValueNames} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar
} -body {
    registry values HKEY_CURRENT_USER\\TclFoobar
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -result baz

test registry-7.3 {GetValueNames} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar {} foobar3
} -body {
    lsort [registry values HKEY_CURRENT_USER\\TclFoobar]
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar

} -result {{} baz blat}
test registry-7.4 {GetValueNames: remote key} -constraints {win reg nonPortable english} -body {
    set hostname [info hostname]
    registry set \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar baz blat
    set result [registry values \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar]
    registry delete \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar
    set result
} -result baz
test registry-7.5 {GetValueNames: empty key} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry values HKEY_CURRENT_USER\\TclFoobar
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -result {}

test registry-7.6 {GetValueNames: patterns} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar foo foobar3
} -body {
    lsort [registry values HKEY_CURRENT_USER\\TclFoobar b*]
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar

} -result {baz blat}
test registry-7.7 {GetValueNames: names with spaces} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz\ bar foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar foo foobar3
} -body {
    lsort [registry values HKEY_CURRENT_USER\\TclFoobar b*]
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar

} -result {{baz bar} blat}

test registry-8.1 {OpenSubKey} -constraints {win reg nonPortable english} \
    -body {
        # This test will only succeed if the current user does not have
        # registry access on the specified machine.
        registry keys {\\mom\HKEY_LOCAL_MACHINE}
    } -returnCodes error -result "unable to open key: Access is denied."
test registry-8.2 {OpenSubKey} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry keys HKEY_CURRENT_USER TclFoobar
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar

} -result {TclFoobar}
test registry-8.3 {OpenSubKey} -constraints {win reg english} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry keys HKEY_CURRENT_USER\\TclFoobar
} -returnCodes error \
    -result "unable to open key: The system cannot find the file specified."

test registry-9.1 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values \\
} -returnCodes error -result "bad key \"\\\": must start with a valid root"
test registry-9.2 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values \\foobar
} -returnCodes error -result {bad key "\foobar": must start with a valid root}
test registry-9.3 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values \\\\
} -returnCodes error -result {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}
test registry-9.4 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values \\\\\\
} -returnCodes error -result {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}
test registry-9.5 {ParseKeyName: bad keys} -constraints {win reg english} -body {
    registry values \\\\\\HKEY_CLASSES_ROOT
} -returnCodes error -result {unable to open key: The network address is invalid.}
test registry-9.6 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values \\\\gaspode
} -returnCodes error -result {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}
test registry-9.7 {ParseKeyName: bad keys} -constraints {win reg} -body {
    registry values foobar
} -returnCodes error -result {bad root name "foobar": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}
test registry-9.8 {ParseKeyName: null keys} -constraints {win reg} -body {
    registry delete HKEY_CLASSES_ROOT\\
} -returnCodes error -result {bad key: cannot delete root keys}
test registry-9.9 {ParseKeyName: null keys} \
    -constraints {win reg english} \
    -body {registry keys HKEY_CLASSES_ROOT\\TclFoobar\\baz} \
    -returnCodes error \
    -result {unable to open key: The system cannot find the file specified.}

test registry-10.1 {RecursiveDeleteKey} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry set HKEY_CURRENT_USER\\TclFoobar\\test1
    registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result [registry keys HKEY_CURRENT_USER TclFoobar]
    set result
} -result {}
test registry-10.2 {RecursiveDeleteKey} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar\\test1
    registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
} -body {
    registry delete HKEY_CURRENT_USER\\TclFoobar\\test2\\test4
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -result {}


test registry-11.1 {SetValue: recursive creation} \
    -constraints {win reg} -setup {
        registry delete HKEY_CURRENT_USER\\TclFoobar
    } -body {
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
        set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
    } -result {foobar}
test registry-11.2 {SetValue: modification} -constraints {win reg} \
    -setup {
        registry delete HKEY_CURRENT_USER\\TclFoobar
    } -body {
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat frob
        set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
    } -result {frob}
test registry-11.3 {SetValue: failure} \
    -constraints {win reg nonPortable english} \
    -body {
        # This test will only succeed if the current user does not have
        # registry access on the specified machine.
        registry set {\\mom\HKEY_CURRENT_USER\TclFoobar} bar foobar
    } -returnCodes error -result {unable to open key: Access is denied.}

test registry-12.1 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast
} -returnCodes error -result "wrong # args: should be \"registry broadcast keyName ?-timeout milliseconds?\""
test registry-12.2 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast "" -time
} -returnCodes error -result "wrong # args: should be \"registry broadcast keyName ?-timeout milliseconds?\""
test registry-12.3 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast "" - 500
} -returnCodes error -result "wrong # args: should be \"registry broadcast keyName ?-timeout milliseconds?\""
test registry-12.4 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast {Environment}
} -result {1 0}
test registry-12.5 {BroadcastValue} -constraints {win reg} -body {
    registry b {}
} -result {1 0}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# tcl-indent-level: 4
# fill-column: 78
# End:







|

















|
|
|


|

|

<
|
|
|


<
|
<

|
>
|




<
|
<

>
|
|





|
|


<
|
<

|
>
|




<
|
<

>
|
|




<
|
<

>
|

|
<
|
|
|
|
|


<
|
<

>
|
|

<
|
<
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|

|

<





|
|



<
|
<

|
>

|
<
|
<
|
|
|
|
<
|
<
|
|
|
|
<
|
<
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|









435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

469
470
471
472
473

474

475
476
477
478
479
480
481
482

483

484
485
486
487
488
489
490
491
492
493
494
495
496

497

498
499
500
501
502
503
504
505

506

507
508
509
510
511
512
513
514

515

516
517
518
519
520

521
522
523
524
525
526
527

528

529
530
531
532
533

534

535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

562

563
564
565
566

567
568
569
570
571
572
573
574
575
576

577

578
579
580
581
582

583

584
585
586
587

588

589
590
591
592

593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
} 1
test registry-6.17 {GetValue: Unicode value names} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar val\u00c71 foobar multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val\u00c71]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} foobar
test registry-6.18 {GetValue: values with Unicode strings} {win reg nt} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u30b7r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba\u30b7r baz"
test registry-6.19 {GetValue: values with Unicode strings} {win reg english} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u00c7r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba\u00c7r baz"
test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {win reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u0000r baz} multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} "foo ba r baz"
test registry-6.21 {GetValue: very long value names and values} {pcOnly reg} {
    registry set HKEY_CURRENT_USER\\TclFoobar [string repeat k 199] [string repeat x 199] multi_sz
    set result [registry get HKEY_CURRENT_USER\\TclFoobar [string repeat k 199]]
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} [string repeat x 199]

test registry-7.1 {GetValueNames: bad key} {win reg english} {
    registry delete HKEY_CURRENT_USER\\TclFoobar

    list [catch {registry values HKEY_CURRENT_USER\\TclFoobar} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
test registry-7.2 {GetValueNames} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar

    set result [registry values HKEY_CURRENT_USER\\TclFoobar]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} baz
test registry-7.3 {GetValueNames} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar {} foobar3

    set result [lsort [registry values HKEY_CURRENT_USER\\TclFoobar]]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} {{} baz blat}
test registry-7.4 {GetValueNames: remote key} {win reg nonPortable english} {
    set hostname [info hostname]
    registry set \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar baz blat
    set result [registry values \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar]
    registry delete \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar
    set result
} baz
test registry-7.5 {GetValueNames: empty key} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar

    set result [registry values HKEY_CURRENT_USER\\TclFoobar]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} {}
test registry-7.6 {GetValueNames: patterns} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar foo foobar3

    set result [lsort [registry values HKEY_CURRENT_USER\\TclFoobar b*]]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} {baz blat}
test registry-7.7 {GetValueNames: names with spaces} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar baz\ bar foobar1
    registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
    registry set HKEY_CURRENT_USER\\TclFoobar foo foobar3

    set result [lsort [registry values HKEY_CURRENT_USER\\TclFoobar b*]]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} {{baz bar} blat}

test registry-8.1 {OpenSubKey} {win reg nonPortable english} {

    # This test will only succeed if the current user does not have registry
    # access on the specified machine.
    list [catch {registry keys {\\mom\HKEY_LOCAL_MACHINE}} msg] $msg
} {1 {unable to open key: Access is denied.}}
test registry-8.2 {OpenSubKey} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar

    set result [registry keys HKEY_CURRENT_USER TclFoobar]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} TclFoobar
test registry-8.3 {OpenSubKey} {win reg english} {
    registry delete HKEY_CURRENT_USER\\TclFoobar

    list [catch {registry keys HKEY_CURRENT_USER\\TclFoobar} msg] $msg

} {1 {unable to open key: The system cannot find the file specified.}}

test registry-9.1 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values \\} msg] $msg
} "1 {bad key \"\\\": must start with a valid root}"
test registry-9.2 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values \\foobar} msg] $msg
} {1 {bad key "\foobar": must start with a valid root}}
test registry-9.3 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values \\\\} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-9.4 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values \\\\\\} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-9.5 {ParseKeyName: bad keys} {win reg english nt} {
    list [catch {registry values \\\\\\HKEY_CURRENT_USER} msg] $msg
} {1 {unable to open key: The network address is invalid.}}
test registry-9.6 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values \\\\gaspode} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-9.7 {ParseKeyName: bad keys} {win reg} {
    list [catch {registry values foobar} msg] $msg
} {1 {bad root name "foobar": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
test registry-9.8 {ParseKeyName: null keys} {win reg} {
    list [catch {registry delete HKEY_CURRENT_USER\\} msg] $msg
} {1 {bad key: cannot delete root keys}}
test registry-9.9 {ParseKeyName: null keys} {win reg english} {

    list [catch {registry keys HKEY_CURRENT_USER\\TclFoobar\\baz} msg] $msg

} {1 {unable to open key: The system cannot find the file specified.}}

test registry-10.1 {RecursiveDeleteKey} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar

    registry set HKEY_CURRENT_USER\\TclFoobar\\test1
    registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result [registry keys HKEY_CURRENT_USER TclFoobar]
    set result
} {}
test registry-10.2 {RecursiveDeleteKey} {win reg} {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar\\test1
    registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3

    set result [registry delete HKEY_CURRENT_USER\\TclFoobar\\test2\\test4]

    registry delete HKEY_CURRENT_USER\\TclFoobar
    set result
} {}

test registry-11.1 {SetValue: recursive creation} {win reg} {

    registry delete HKEY_CURRENT_USER\\TclFoobar

    registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
    set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
} foobar
test registry-11.2 {SetValue: modification} {win reg} {

    registry delete HKEY_CURRENT_USER\\TclFoobar

    registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
    registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat frob
    set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
} frob

test registry-11.3 {SetValue: failure} {win reg nonPortable english} {

    # This test will only succeed if the current user does not have registry
    # access on the specified machine.
    list [catch {registry set {\\mom\HKEY_CURRENT_USER\TclFoobar} bar foobar} msg] $msg
} {1 {unable to open key: Access is denied.}}

test registry-12.1 {BroadcastValue} {win reg} {
    list [catch {registry broadcast} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
test registry-12.2 {BroadcastValue} {win reg} {
    list [catch {registry broadcast "" -time} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
test registry-12.3 {BroadcastValue} {win reg} {
    list [catch {registry broadcast "" - 500} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
test registry-12.4 {BroadcastValue} {win reg} {
    list [catch {registry broadcast {Environment}} msg] $msg
} {0 {1 0}}
test registry-12.5 {BroadcastValue} {win reg} {
    list [catch {registry b {}} msg] $msg
} {0 {1 0}}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# tcl-indent-level: 4
# fill-column: 78
# End:

Changes to tests/safe.test.

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
foreach i [interp slaves] {
    interp delete $i
}

set saveAutoPath $::auto_path
set ::auto_path [info library]

# Force actual loading of the safe package
# because we use un exported (and thus un-autoindexed) APIs
# in this test result arguments:
catch {safe::interpConfigure}

proc equiv {x} {return $x}

test safe-1.1 {safe::interpConfigure syntax} {
    list [catch {safe::interpConfigure} msg] $msg;
} {1 {no value given for parameter "slave" (use -help for full usage) :
    slave name () name of the slave}}
test safe-1.2 {safe::interpCreate syntax} {
    list [catch {safe::interpCreate -help} msg] $msg;
} {1 {Usage information:
    Var/FlagName  Type     Value   Help
    ------------  ----     -----   ----
    (-help                         gives this help)
    ?slave?       name     ()      name of the slave (optional)
    -accessPath   list     ()      access path for the slave
    -noStatics    boolflag (false) prevent loading of statically linked pkgs
    -statics      boolean  (true)  loading of statically linked pkgs
    -nestedLoadOk boolflag (false) allow nested loading
    -nested       boolean  (false) nested loading
    -deleteHook   script   ()      delete hook}}







|















|







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
foreach i [interp slaves] {
    interp delete $i
}

set saveAutoPath $::auto_path
set ::auto_path [info library]

# Force actual loading of the safe package 
# because we use un exported (and thus un-autoindexed) APIs
# in this test result arguments:
catch {safe::interpConfigure}

proc equiv {x} {return $x}

test safe-1.1 {safe::interpConfigure syntax} {
    list [catch {safe::interpConfigure} msg] $msg;
} {1 {no value given for parameter "slave" (use -help for full usage) :
    slave name () name of the slave}}
test safe-1.2 {safe::interpCreate syntax} {
    list [catch {safe::interpCreate -help} msg] $msg;
} {1 {Usage information:
    Var/FlagName  Type     Value   Help
    ------------  ----     -----   ----
    ( -help                        gives this help )
    ?slave?       name     ()      name of the slave (optional)
    -accessPath   list     ()      access path for the slave
    -noStatics    boolflag (false) prevent loading of statically linked pkgs
    -statics      boolean  (true)  loading of statically linked pkgs
    -nestedLoadOk boolflag (false) allow nested loading
    -nested       boolean  (false) nested loading
    -deleteHook   script   ()      delete hook}}
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    set l [a aliases]
    interp delete a
    lsort $l
} {::tcl::mathfunc::max ::tcl::mathfunc::min clock}

test safe-3.1 {calling safe::interpInit is safe} {
    catch {safe::interpDelete a}
    interp create a -safe
    safe::interpInit a
    catch {interp eval a exec ls} msg
    safe::interpDelete a
    set msg
} {invalid command name "exec"}
test safe-3.2 {calling safe::interpCreate on trusted interp} {
    catch {safe::interpDelete a}







|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    set l [a aliases]
    interp delete a
    lsort $l
} {::tcl::mathfunc::max ::tcl::mathfunc::min clock}

test safe-3.1 {calling safe::interpInit is safe} {
    catch {safe::interpDelete a}
    interp create a -safe 
    safe::interpInit a
    catch {interp eval a exec ls} msg
    safe::interpDelete a
    set msg
} {invalid command name "exec"}
test safe-3.2 {calling safe::interpCreate on trusted interp} {
    catch {safe::interpDelete a}

Changes to tests/set-old.test.

915
916
917
918
919
920
921
922
catch {unset a}
catch {unset b}
catch {unset c}
catch {unset aVaRnAmE}

# cleanup
::tcltest::cleanupTests
return







|
915
916
917
918
919
920
921
922
catch {unset a}
catch {unset b}
catch {unset c}
catch {unset aVaRnAmE}

# cleanup
::tcltest::cleanupTests
return 

Changes to tests/set.test.

529
530
531
532
533
534
535
536
# cleanup
catch {unset a}
catch {unset b}
catch {unset i}
catch {unset x}
catch {unset z}
::tcltest::cleanupTests
return







|
529
530
531
532
533
534
535
536
# cleanup
catch {unset a}
catch {unset b}
catch {unset i}
catch {unset x}
catch {unset z}
::tcltest::cleanupTests
return 

Changes to tests/socket.test.

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# server (via exec) on platforms that support this, on the local host,
# listening at port 2048. If all fails, a message is printed and the tests
# using the remote server are not performed.

package require tcltest 2
namespace import -force ::tcltest::*

if {[expr {[info exists ::env(TRAVIS_OSX_IMAGE)] && [string match xcode* $::env(TRAVIS_OSX_IMAGE)]}]} {
    return
}

# Some tests require the testthread and exec commands
testConstraint testthread [llength [info commands testthread]]
testConstraint exec [llength [info commands exec]]

# Produce a random port number in the Dynamic/Private range
# from 49152 through 65535.
proc randport {} { expr {int(rand()*16383+49152)} }







<
<
<
<







59
60
61
62
63
64
65




66
67
68
69
70
71
72
# server (via exec) on platforms that support this, on the local host,
# listening at port 2048. If all fails, a message is printed and the tests
# using the remote server are not performed.

package require tcltest 2
namespace import -force ::tcltest::*





# Some tests require the testthread and exec commands
testConstraint testthread [llength [info commands testthread]]
testConstraint exec [llength [info commands exec]]

# Produce a random port number in the Dynamic/Private range
# from 49152 through 65535.
proc randport {} { expr {int(rand()*16383+49152)} }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	    } else {
		append resp $line "\n"
	    }
	}
    }
}

testConstraint notOSX [string compare $::tcl_platform(os) Darwin]

test socket-1.1 {arg parsing for socket command} {socket} {
    list [catch {socket -server} msg] $msg
} {1 {no argument given for -server option}}
test socket-1.2 {arg parsing for socket command} {socket} {
    list [catch {socket -server foo} msg] $msg
} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.3 {arg parsing for socket command} {socket} {







<
<







191
192
193
194
195
196
197


198
199
200
201
202
203
204
	    } else {
		append resp $line "\n"
	    }
	}
    }
}



test socket-1.1 {arg parsing for socket command} {socket} {
    list [catch {socket -server} msg] $msg
} {1 {no argument given for -server option}}
test socket-1.2 {arg parsing for socket command} {socket} {
    list [catch {socket -server foo} msg] $msg
} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.3 {arg parsing for socket command} {socket} {
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
    } else {
	close $msg
    }
    set x
} ok

test socket-5.1 {byte order problems, socket numbers, htons} \
	{socket unix notRoot notOSX} {
    set x {couldn't open socket: not owner}
    if {![catch {socket -server dodo 0x1} msg]} {
        set x {htons problem, should be disallowed, are you running as SU?}
	close $msg
    }
    set x
} {couldn't open socket: not owner}
test socket-5.2 {byte order problems, socket numbers, htons} {socket} {
    set x {couldn't open socket: port number too high}
    if {![catch {socket -server dodo 0x10000} msg]} {
	set x {port resolution problem, should be disallowed}
	close $msg
    }
    set x
} {couldn't open socket: port number too high}
test socket-5.3 {byte order problems, socket numbers, htons} \
	{socket unix notRoot notOSX} {
    set x {couldn't open socket: not owner}
    if {![catch {socket -server dodo 21} msg]} {
	set x {htons problem, should be disallowed, are you running as SU?}
	close $msg
    }
    set x
} {couldn't open socket: not owner}







|
















|







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
    } else {
	close $msg
    }
    set x
} ok

test socket-5.1 {byte order problems, socket numbers, htons} \
	{socket unix notRoot} {
    set x {couldn't open socket: not owner}
    if {![catch {socket -server dodo 0x1} msg]} {
        set x {htons problem, should be disallowed, are you running as SU?}
	close $msg
    }
    set x
} {couldn't open socket: not owner}
test socket-5.2 {byte order problems, socket numbers, htons} {socket} {
    set x {couldn't open socket: port number too high}
    if {![catch {socket -server dodo 0x10000} msg]} {
	set x {port resolution problem, should be disallowed}
	close $msg
    }
    set x
} {couldn't open socket: port number too high}
test socket-5.3 {byte order problems, socket numbers, htons} \
	{socket unix notRoot} {
    set x {couldn't open socket: not owner}
    if {![catch {socket -server dodo 21} msg]} {
	set x {htons problem, should be disallowed, are you running as SU?}
	close $msg
    }
    set x
} {couldn't open socket: not owner}
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
    vwait x
    after cancel $timer
    close $s
    close $s1
    set l ""
    lappend l [expr {[lindex $x 2] == $listen}] [llength $x]
} {1 3}
test socket-7.5 {testing socket specific options} {socket unixOrWin} {
    set s [socket -server accept 0]
    proc accept {s a p} {
	global x
	set x [fconfigure $s -sockname]
	close $s
    }
    set listen [lindex [fconfigure $s -sockname] 2]







|







941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
    vwait x
    after cancel $timer
    close $s
    close $s1
    set l ""
    lappend l [expr {[lindex $x 2] == $listen}] [llength $x]
} {1 3}
test socket-7.5 {testing socket specific options} {socket unixOrPc} {
    set s [socket -server accept 0]
    proc accept {s a p} {
	global x
	set x [fconfigure $s -sockname]
	close $s
    }
    set listen [lindex [fconfigure $s -sockname] 2]
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
   puts $commandSocket exit
   flush $commandSocket
}
catch {close $commandSocket}
catch {close $remoteProcChan}
test socket-14.13 {testing writable event when quick failure} -constraints {socket win supported_inet} -body {
    # Test for bug 336441ed59 where a quick background fail was ignored

    # Test only for windows as socket -async 255.255.255.255 fails
    # directly on unix

    # The following connect should fail very quickly
    set a1 [after 2000 {set x timeout}]
    set s [socket -async 255.255.255.255 43434]
    fileevent $s writable {set x writable}
    vwait x
    set x
} -cleanup {
    catch {close $s}
    after cancel $a1
} -result writable

test socket-14.14 {testing fileevent readable on failed async socket connect} -constraints [list socket] -body {
    # Test for bug 581937ab1e

    set a1 [after 5000 {set x timeout}]
    # This connect should fail
    set s [socket -async localhost [randport]]
    fileevent $s readable {set x readable}
    vwait x
    set x
} -cleanup {







|


|













|







1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
   puts $commandSocket exit
   flush $commandSocket
}
catch {close $commandSocket}
catch {close $remoteProcChan}
test socket-14.13 {testing writable event when quick failure} -constraints {socket win supported_inet} -body {
    # Test for bug 336441ed59 where a quick background fail was ignored
    
    # Test only for windows as socket -async 255.255.255.255 fails
    # directly on unix
    
    # The following connect should fail very quickly
    set a1 [after 2000 {set x timeout}]
    set s [socket -async 255.255.255.255 43434]
    fileevent $s writable {set x writable}
    vwait x
    set x
} -cleanup {
    catch {close $s}
    after cancel $a1
} -result writable

test socket-14.14 {testing fileevent readable on failed async socket connect} -constraints [list socket] -body {
    # Test for bug 581937ab1e
    
    set a1 [after 5000 {set x timeout}]
    # This connect should fail
    set s [socket -async localhost [randport]]
    fileevent $s readable {set x readable}
    vwait x
    set x
} -cleanup {

Changes to tests/stack.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import ::tcltest::*

testConstraint noOsx [expr {[info exists ::env(TRAVIS_OSX_IMAGE)] && [string match xcode* $::env(TRAVIS_OSX_IMAGE)]}]

# Note that a failure in this test results in a crash of the executable.
# In order to avoid that, we do a basic check of the current stacksize.
# This size can be changed with ulimit (ksh/bash/sh) or limit (csh/tcsh).

# This doesn't catch all cases, for example threads of lower stacksize
# can still squeak through.  A core check is really needed. -- JH








<
<







8
9
10
11
12
13
14


15
16
17
18
19
20
21
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2
namespace import ::tcltest::*



# Note that a failure in this test results in a crash of the executable.
# In order to avoid that, we do a basic check of the current stacksize.
# This size can be changed with ulimit (ksh/bash/sh) or limit (csh/tcsh).

# This doesn't catch all cases, for example threads of lower stacksize
# can still squeak through.  A core check is really needed. -- JH

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	catch { unknown } msg
	puts $msg
    }
} -match stackOverflow 
    
# Make sure that there is enough stack to run regexp even if we're
# close to the recursion limit. [Bug 947070] [Patch 746378]
test stack-3.1 {enough room for regexp near recursion limit} -constraints noOsx -body {
    # do this in a sub process in case it segfaults
    exec [interpreter] << {
	interp recursionlimit {} 10000
	set depth 0
	proc a { max } {
	    if { [info level] < $max } {
		set ::depth [info level]







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
	catch { unknown } msg
	puts $msg
    }
} -match stackOverflow 
    
# Make sure that there is enough stack to run regexp even if we're
# close to the recursion limit. [Bug 947070] [Patch 746378]
test stack-3.1 {enough room for regexp near recursion limit} -body {
    # do this in a sub process in case it segfaults
    exec [interpreter] << {
	interp recursionlimit {} 10000
	set depth 0
	proc a { max } {
	    if { [info level] < $max } {
		set ::depth [info level]

Changes to tests/string.test.

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    proc foo {} {string compare "a\x00" "a\x01"}
    foo
} -1
test string-2.33 {string compare, high bit} {
    proc foo {} {string compare "\x00\x00" "\x00\x01"}
    foo
} -1
test string-2.34 {string compare, binary equal} {
    proc foo {} {string compare [binary format a100 0] [binary format a100 0]}
   foo
} 0
test string-2.35 {string compare, binary neq} {
    proc foo {} {string compare [binary format a100a 0 1] [binary format a100a 0 0]}
    foo
} 1
test string-2.36 {string compare, binary neq unequal length} {
    proc foo {} {string compare [binary format a20a 0 1] [binary format a100a 0 0]}
    foo
} 1

# only need a few tests on equal, since it uses the same code as
# string compare, but just modifies the return output
test string-3.1 {string equal} {
    string equal abcde abdef
} 0
test string-3.2 {string equal} {







<
<
<
<
<
<
<
<
<
<
<
<







137
138
139
140
141
142
143












144
145
146
147
148
149
150
    proc foo {} {string compare "a\x00" "a\x01"}
    foo
} -1
test string-2.33 {string compare, high bit} {
    proc foo {} {string compare "\x00\x00" "\x00\x01"}
    foo
} -1













# only need a few tests on equal, since it uses the same code as
# string compare, but just modifies the return output
test string-3.1 {string equal} {
    string equal abcde abdef
} 0
test string-3.2 {string equal} {
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    string first \u7266 abc\u7266x end-2
} 3
test string-4.14 {string first, negative start index} {
    string first b abc -1
} 1
test string-4.15 {string first, ability to two-byte encoded utf-8 chars} {
    # Test for a bug in Tcl 8.3 where test for all-single-byte-encoded
    # strings was incorrect, leading to an index returned by [string first]
    # which pointed past the end of the string.
    set uchar \u057e    ;# character with two-byte encoding in utf-8
    string first % %#$uchar$uchar#$uchar$uchar#% 3
} 8
test string-4.17 {string first, corner case} {
    string first a aaa 4294967295
} {0}
test string-4.18 {string first, corner case} {
    string first a aaa -1
} {0}
test string-4.19 {string first, corner case} {
    string first a aaa end-5
} {0}
test string-4.20 {string last, corner case} {
    string last a aaa 4294967295
} {-1}
test string-4.21 {string last, corner case} {
    string last a aaa -1
} {-1}
test string-4.22 {string last, corner case} {
    string last a aaa end-5
} {-1}

test string-5.1 {string index} {
    list [catch {string index} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}
test string-5.2 {string index} {
    list [catch {string index a b c} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}







|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







209
210
211
212
213
214
215
216
217
218
219
220


















221
222
223
224
225
226
227
    string first \u7266 abc\u7266x end-2
} 3
test string-4.14 {string first, negative start index} {
    string first b abc -1
} 1
test string-4.15 {string first, ability to two-byte encoded utf-8 chars} {
    # Test for a bug in Tcl 8.3 where test for all-single-byte-encoded
    # strings was incorrect, leading to an index returned by [string first] 
    # which pointed past the end of the string.
    set uchar \u057e    ;# character with two-byte encoding in utf-8
    string first % %#$uchar$uchar#$uchar$uchar#% 3
} 8



















test string-5.1 {string index} {
    list [catch {string index} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}
test string-5.2 {string index} {
    list [catch {string index a b c} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
    # Since bignums arrived in Tcl 8.5, the sense of this test changed.
    # Now integer values that exceed native limits become bignums, and
    # bignums can convert to doubles without error.
    list [string is double -fail var [largest_int]0] $var
} -result {1 priorValue}
# string-6.38 removed, underflow on input is no longer an error.
test string-6.39 {string is double, false} {
    # This test is non-portable because IRIX thinks
    # that .e1 is a valid double - this is really a bug
    # on IRIX as .e1 should NOT be a valid double
    #
    # Portable now. Tcl 8.5 does its own double parsing.

    list [string is double -fail var .e1] $var
} {0 0}







|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
    # Since bignums arrived in Tcl 8.5, the sense of this test changed.
    # Now integer values that exceed native limits become bignums, and
    # bignums can convert to doubles without error.
    list [string is double -fail var [largest_int]0] $var
} -result {1 priorValue}
# string-6.38 removed, underflow on input is no longer an error.
test string-6.39 {string is double, false} {
    # This test is non-portable because IRIX thinks 
    # that .e1 is a valid double - this is really a bug
    # on IRIX as .e1 should NOT be a valid double
    #
    # Portable now. Tcl 8.5 does its own double parsing.

    list [string is double -fail var .e1] $var
} {0 0}
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
} {    XYZ}
test string-20.4 {string trimright} {
    string trimright "   "
} {}
test string-20.5 {string trimright} {
    string trimright ""
} {}
test string-20.6 {string trimright, unicode default} {
    # Reserve test number for Tcl 8.6 (TIP 413)
} {}
test string-20.7 {string trim on not valid utf-8 sequence (consider NTS as continuation char), bug [c61818e4c9]} {
    set result {}
    set a [bytestring \xc0\x80\xA0]
    set b foo$a
    set m [list \u0000 U \xA0 V [bytestring \xA0] W]
    lappend result [string map $m $b]
    lappend result [string map $m [string trimright $b x]]
    lappend result [string map $m [string trimright $b \u0000]]
    lappend result [string map $m [string trimleft $b fox]]
    lappend result [string map $m [string trimleft $b fo\u0000]]
    lappend result [string map $m [string trim $b fox]]
    lappend result [string map $m [string trim $b fo\u0000]]
} [list {*}[lrepeat 3 fooUV] {*}[lrepeat 2 UV V]]
test string-20.8 {[c61818e4c9] [string trimright] fails when UtfPrev is ok} {
    set result {}
    set a [bytestring \xE8\xA0]
    set b foo$a
    set m [list \xE8 U \xA0 V [bytestring \xE8] W [bytestring \xA0] X]]
    lappend result [string map $m $b]
    lappend result [string map $m [string trimright $b x]]
    lappend result [string map $m [string trimright $b \xE8]]
    lappend result [string map $m [string trimright $b [bytestring \xE8]]]
    lappend result [string map $m [string trimright $b \xA0]]
    lappend result [string map $m [string trimright $b [bytestring \xA0]]]
    lappend result [string map $m [string trimright $b \xE8\xA0]]
    lappend result [string map $m [string trimright $b [bytestring \xE8\xA0]]]
    lappend result [string map $m [string trimright $b \u0000]]
} [list {*}[lrepeat 4 fooUV] {*}[lrepeat 2 fooU] {*}[lrepeat 2 foo] fooUV]

test string-21.1 {string wordend} {
    list [catch {string wordend a} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}
test string-21.2 {string wordend} {
    list [catch {string wordend a b c} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1437
1438
1439
1440
1441
1442
1443































1444
1445
1446
1447
1448
1449
1450
} {    XYZ}
test string-20.4 {string trimright} {
    string trimright "   "
} {}
test string-20.5 {string trimright} {
    string trimright ""
} {}
































test string-21.1 {string wordend} {
    list [catch {string wordend a} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}
test string-21.2 {string wordend} {
    list [catch {string wordend a b c} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
} 4
test string-22.12 {string wordstart, unicode} {
    string wordstart "ab\uc700\uc700 cdef ghi" 12
} 10
test string-22.13 {string wordstart, unicode} {
    string wordstart "\uc700\uc700 abc" 8
} 3
test string-22.14 {string wordstart, invalid UTF-8} {
    # See Bug c61818e4c9
    set demo [bytestring "abc def\xE0\xA9ghi"]
    string index $demo [string wordstart $demo 10]
} g

test string-23.0 {string is boolean, Bug 1187123} testindexobj {
    set x 5
    catch {testindexobj $x foo bar soom}
    string is boolean $x
} 0
test string-23.1 {string is command with empty string} {







<
<
<
<
<







1520
1521
1522
1523
1524
1525
1526





1527
1528
1529
1530
1531
1532
1533
} 4
test string-22.12 {string wordstart, unicode} {
    string wordstart "ab\uc700\uc700 cdef ghi" 12
} 10
test string-22.13 {string wordstart, unicode} {
    string wordstart "\uc700\uc700 abc" 8
} 3






test string-23.0 {string is boolean, Bug 1187123} testindexobj {
    set x 5
    catch {testindexobj $x foo bar soom}
    string is boolean $x
} 0
test string-23.1 {string is command with empty string} {

Changes to tests/stringObj.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
# Commands covered: none
#
# This file contains tests for the procedures in tclStringObj.c that implement
# the Tcl type manager for the string type.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint testobj [llength [info commands testobj]]
testConstraint testdstring [llength [info commands testdstring]]

test stringObj-1.1 {string type registration} testobj {
    set t [testobj types]
    set first [string first "string" $t]
    set result [expr {$first != -1}]
} {1}

test stringObj-2.1 {Tcl_NewStringObj} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [teststringobj set 1 abcd]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} abcd string 2}

test stringObj-3.1 {Tcl_SetStringObj, existing "empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testobj newobj 1]
    lappend result [teststringobj set 1 xyz]	;# makes existing obj a string
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} {} xyz string 2}
test stringObj-3.2 {Tcl_SetStringObj, existing non-"empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testintobj set 1 512]
    lappend result [teststringobj set 1 foo]	;# makes existing obj a string
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 512 foo string 2}

test stringObj-4.1 {Tcl_SetObjLength procedure, string gets shorter} testobj {
    testobj freeallvars
    teststringobj set 1 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
# Commands covered: none
#
# This file contains tests for the procedures in tclStringObj.c
# that implement the Tcl type manager for the string type.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint testobj [llength [info commands testobj]]
testConstraint testdstring [llength [info commands testdstring]]

test stringObj-1.1 {string type registration} testobj {
    set t [testobj types]
    set first [string first "string" $t]
    set result [expr {$first != -1}]
} {1}

test stringObj-2.1 {Tcl_NewStringObj} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [teststringobj set 1 abcd]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} abcd string 2}

test stringObj-3.1 {Tcl_SetStringObj, existing "empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testobj newobj 1]
    lappend result [teststringobj set 1 xyz] ;# makes existing obj a string
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} {} xyz string 2}
test stringObj-3.2 {Tcl_SetStringObj, existing non-"empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testintobj set 1 512]
    lappend result [teststringobj set 1 foo]  ;# makes existing obj a string
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 512 foo string 2}

test stringObj-4.1 {Tcl_SetObjLength procedure, string gets shorter} testobj {
    testobj freeallvars
    teststringobj set 1 test
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    testobj duplicate 1 2
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj ualloc 1] [teststringobj get 1] \
	    [teststringobj length 2] [teststringobj length2 2] \
	    [teststringobj ualloc 2] [teststringobj get 2]
} {5 10 0 abcde 5 5 0 abcde}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string"
test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string"
test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} testobj {
    set x abcdefghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x jkl] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}







|


|

|

|


|

|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    testobj duplicate 1 2
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj ualloc 1] [teststringobj get 1] \
	    [teststringobj length 2] [teststringobj length2 2] \
	    [teststringobj ualloc 2] [teststringobj get 2]
} {5 10 0 abcde 5 5 0 abcde}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abcï¿®ghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x "���"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abc○ghi��� abc○ghi string string}
test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abcï¿®ghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x "���"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abc○ghi��� abc○ghi string string}
test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} testobj {
    set x abcdefghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x jkl] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    testdstring append \u00ae\u00bf\u00ef -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
            [set y] [testobj objtype $x] [testobj objtype $y]
} "string none abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none"
test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    string length $x
    list [testobj objtype $x] [append x $x] [testobj objtype $x] \
	    [append x $x] [testobj objtype $x]
} "string abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi string\
abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi\
string"
test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {testobj testdstring} {
    set x abcdefghi
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \







|



|
|
|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    testdstring append \u00ae\u00bf\u00ef -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
            [set y] [testobj objtype $x] [testobj objtype $y]
} "string none abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none"
test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
    set x abcï¿®ghi
    string length $x
    list [testobj objtype $x] [append x $x] [testobj objtype $x] \
	    [append x $x] [testobj objtype $x]
} {string abcï¿®ghiabcï¿®ghi string\
abcï¿®ghiabcï¿®ghiabcï¿®ghiabcï¿®ghi\
string}
test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {testobj testdstring} {
    set x abcdefghi
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
    set x abcdefghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcdefghi9 9 string int}
test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string int abc\u00ef\u00bf\u00aeghi9 9 string int"
test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} testobj {
    # bug 2678, in <=8.2.0, the second obj (the one to append) in
    # Tcl_AppendObjToObj was not correctly checked to see if it was all one
    # byte chars, so a unicode string would be added as one byte chars.

    set x abcdef
    set len [string length $x]
    set y a\u00fcb\u00e5c\u00ef
    set len [string length $y]
    append x $y
    string length $x
    set q {}
    for {set i 0} {$i < 12} {incr i} {
	lappend q [string index $x $i]
    }
    set q
} "a b c d e f a \u00fc b \u00e5 c \u00ef"

test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {testobj testdstring} {
    testdstring free
    testdstring append abcdef -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
            [testobj objtype $x] [testobj objtype $y]
} [list none bcde string string]
test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {testobj testdstring} {
    # Because this test does not use \uXXXX notation below instead of
    # hardcoding the values, it may fail in multibyte locales. However, we
    # need to test that the parser produces untyped objects even when there
    # are high-ASCII characters in the input (like "ï"). I don't know what
    # else to do but inline those characters here.
    testdstring free
    testdstring append "abc\u00ef\u00efdef" -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
            [testobj objtype $x] [testobj objtype $y]
} [list none "bc\u00EF\u00EFde" string string]
test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
    # set x "abcïïdef"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set x "abc\u00EF\u00EFdef"
    string length $x
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [list string "bc\u00EF\u00EFde" string string]
test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj {
    # set a "ïa¿b®cï¿d®"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    set result [list]
    while {[string length $a] > 0} {
	set a [string range $a 1 end-1]
	lappend result $a







|




|


|
|
>


|








|












|








|








|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    set x abcdefghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcdefghi9 9 string int}
test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} testobj {
    set x abcï¿®ghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcï¿®ghi9 9 string int}
test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} testobj {
    # bug 2678, in <=8.2.0, the second obj (the one to append) in
    # Tcl_AppendObjToObj was not correctly checked to see if it was
    # all one byte chars, so a unicode string would be added as one
    # byte chars.
    set x abcdef
    set len [string length $x]
    set y a�b�c�
    set len [string length $y]
    append x $y
    string length $x
    set q {}
    for {set i 0} {$i < 12} {incr i} {
	lappend q [string index $x $i]
    }
    set q
} {a b c d e f a � b � c �}

test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {testobj testdstring} {
    testdstring free
    testdstring append abcdef -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
            [testobj objtype $x] [testobj objtype $y]
} [list none bcde string string]
test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {testobj testdstring} {
    # Because this test does not use \uXXXX notation below instead of
    # hardcoding the values, it may fail in multibyte locales. However, we
    # need to test that the parser produces untyped objects even when there
    # are high-ASCII characters in the input (like "�"). I don't know what
    # else to do but inline those characters here.
    testdstring free
    testdstring append "abc\u00ef\u00efdef" -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
            [testobj objtype $x] [testobj objtype $y]
} [list none "bc\u00EF\u00EFde" string string]
test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
    # set x "abc��def"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set x "abc\u00EF\u00EFdef"
    string length $x
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [list string "bc\u00EF\u00EFde" string string]
test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj {
    # set a "�a�b�c�d�"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    set result [list]
    while {[string length $a] > 0} {
	set a [string range $a 1 end-1]
	lappend result $a
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
    list [string index $x 3] [string index $x end]
} {d i}
test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} testobj {
    set x "abcdefghi"
    list [string index $x end] [string index $x end-1]
} {i h}
test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} testobj {
    string index "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef" 0
} "\u00ef"
test stringObj-12.5 {Tcl_GetUniChar} testobj {
    set x "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef"
    list [string index $x 4] [string index $x 0]
} "\u00ae \u00ef"
test stringObj-12.6 {Tcl_GetUniChar} testobj {
    string index "\u00efa\u00bfb\u00aec\u00ef\u00bfd\u00ae" end
} "\u00ae"

test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} testobj {
    set a ""
    list [string length $a] [string length $a]
} {0 0}
test stringObj-13.2 {Tcl_GetCharLength with byte-size chars} testobj {
    string length "a"
} 1
test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} testobj {
    set a "abcdef"
    list [string length $a] [string length $a]
} {6 6}
test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} testobj {
    string length "\u00ae"
} 1
test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
    # string length "○○"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE"
} 6
test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} testobj {
    # set a "ïa¿b®cï¿d®"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    list [string length $a] [string length $a]
} {10 10}
test stringObj-13.7 {Tcl_GetCharLength with identity nulls} testobj {
    # SF bug #684699
    string length [bytestring \x00]
} 1
test stringObj-13.8 {Tcl_GetCharLength with identity nulls} testobj {
    string length [bytestring \x01\x00\x02]
} 3

test stringObj-14.1 {Tcl_SetObjLength on pure unicode object} testobj {
    teststringobj set 1 foo
    teststringobj getunicode 1
    teststringobj append 1 bar -1
    teststringobj getunicode 1







|
|

|

|

|
|













|


|





|







|


|







385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    list [string index $x 3] [string index $x end]
} {d i}
test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} testobj {
    set x "abcdefghi"
    list [string index $x end] [string index $x end-1]
} {i h}
test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} testobj {
    string index "�a�b�c��d�" 0
} "�"
test stringObj-12.5 {Tcl_GetUniChar} testobj {
    set x "�a�b�c��d�"
    list [string index $x 4] [string index $x 0]
} {� �}
test stringObj-12.6 {Tcl_GetUniChar} testobj {
    string index "�a�b�c�d�" end
} "�"

test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} testobj {
    set a ""
    list [string length $a] [string length $a]
} {0 0}
test stringObj-13.2 {Tcl_GetCharLength with byte-size chars} testobj {
    string length "a"
} 1
test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} testobj {
    set a "abcdef"
    list [string length $a] [string length $a]
} {6 6}
test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} testobj {
    string length "�" 
} 1
test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
    # string length "○○" 
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE"
} 6
test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} testobj {
    # set a "�a�b�c�d�"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    list [string length $a] [string length $a]
} {10 10}
test stringObj-13.7 {Tcl_GetCharLength with identity nulls} testobj {
    # SF bug #684699
    string length [encoding convertfrom identity \x00]
} 1
test stringObj-13.8 {Tcl_GetCharLength with identity nulls} testobj {
    string length [encoding convertfrom identity \x01\x00\x02]
} 3

test stringObj-14.1 {Tcl_SetObjLength on pure unicode object} testobj {
    teststringobj set 1 foo
    teststringobj getunicode 1
    teststringobj append 1 bar -1
    teststringobj getunicode 1

Changes to tests/subst.test.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    subst [bytestring bar\x00soom]
} [bytestring bar\x00soom]

test subst-3.1 {backslash substitutions} {
    subst {\x\$x\[foo bar]\\}
} "x\$x\[foo bar]\\"
test subst-3.2 {backslash substitutions with utf chars} {
    # 'j' is just a char that doesn't mean anything, and \344 is 'ä'
    # that also doesn't mean anything, but is multi-byte in UTF-8.
    list [subst \j] [subst \\j] [subst \\344] [subst \\\344]
} "j j \344 \344"

test subst-4.1 {variable substitutions} {
    set a 44
    subst {$a}







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    subst [bytestring bar\x00soom]
} [bytestring bar\x00soom]

test subst-3.1 {backslash substitutions} {
    subst {\x\$x\[foo bar]\\}
} "x\$x\[foo bar]\\"
test subst-3.2 {backslash substitutions with utf chars} {
    # 'j' is just a char that doesn't mean anything, and \344 is '�'
    # that also doesn't mean anything, but is multi-byte in UTF-8.
    list [subst \j] [subst \\j] [subst \\344] [subst \\\344]
} "j j \344 \344"

test subst-4.1 {variable substitutions} {
    set a 44
    subst {$a}
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
    subst {x.[concat foo].y.[concat bar].z}
} {x.foo.y.bar.z}
test subst-5.4 {command substitutions} {
    list [catch {subst {$long [set long] [bogus_command]}} msg] $msg
} {1 {invalid command name "bogus_command"}}
test subst-5.5 {command substitutions} {
    set a 0
    list [catch {subst {[set a 1}} msg] $a $msg
} {1 0 {missing close-bracket}}
test subst-5.6 {command substitutions} {
    set a 0
    list [catch {subst {0[set a 1}} msg] $a $msg
} {1 0 {missing close-bracket}}
test subst-5.7 {command substitutions} {
    set a 0
    list [catch {subst {0[set a 1; set a 2}} msg] $a $msg
} {1 1 {missing close-bracket}}

# repeat the tests above simulating cmd line input
test subst-5.8 {command substitutions} {
    set script {[subst {[set a 1}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg
} {1 {missing close-bracket}}
test subst-5.9 {command substitutions} {
    set script {[subst {0[set a 1}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg
} {1 {missing close-bracket}}
test subst-5.10 {command substitutions} {
    set script {[subst {0[set a 1; set a 2}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg
} {1 {missing close-bracket}}

test subst-6.1 {clear the result after command substitution} {
    catch {unset a}
    list [catch {subst {[concat foo] $a}} msg] $msg
} {1 {can't read "a": no such variable}}








|



|



|





|



|



|







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
    subst {x.[concat foo].y.[concat bar].z}
} {x.foo.y.bar.z}
test subst-5.4 {command substitutions} {
    list [catch {subst {$long [set long] [bogus_command]}} msg] $msg
} {1 {invalid command name "bogus_command"}}
test subst-5.5 {command substitutions} {
    set a 0
    list [catch {subst {[set a 1}} msg] $a $msg 
} {1 0 {missing close-bracket}}
test subst-5.6 {command substitutions} {
    set a 0
    list [catch {subst {0[set a 1}} msg] $a $msg 
} {1 0 {missing close-bracket}}
test subst-5.7 {command substitutions} {
    set a 0
    list [catch {subst {0[set a 1; set a 2}} msg] $a $msg 
} {1 1 {missing close-bracket}}

# repeat the tests above simulating cmd line input
test subst-5.8 {command substitutions} {
    set script {[subst {[set a 1}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg 
} {1 {missing close-bracket}}
test subst-5.9 {command substitutions} {
    set script {[subst {0[set a 1}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg 
} {1 {missing close-bracket}}
test subst-5.10 {command substitutions} {
    set script {[subst {0[set a 1; set a 2}]}
    list [catch {exec [info nameofexecutable] << $script} msg] $msg 
} {1 {missing close-bracket}}

test subst-6.1 {clear the result after command substitution} {
    catch {unset a}
    list [catch {subst {[concat foo] $a}} msg] $msg
} {1 {can't read "a": no such variable}}

Changes to tests/tcltest.test.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    } {}
    tcltest::cleanupTests
    exit
} test.tcl

cd [temporaryDirectory]
testConstraint exec [llength [info commands exec]]

# test -help
# Child processes because -help [exit]s.
test tcltest-1.1 {tcltest -help} {exec} {
    set result [catch {exec [interpreter] test.tcl -help} msg]
    list $result [regexp Usage $msg]
} {1 1}
test tcltest-1.2 {tcltest -help -something} {exec} {







<







42
43
44
45
46
47
48

49
50
51
52
53
54
55
    } {}
    tcltest::cleanupTests
    exit
} test.tcl

cd [temporaryDirectory]
testConstraint exec [llength [info commands exec]]

# test -help
# Child processes because -help [exit]s.
test tcltest-1.1 {tcltest -help} {exec} {
    set result [catch {exec [interpreter] test.tcl -help} msg]
    list $result [regexp Usage $msg]
} {1 1}
test tcltest-1.2 {tcltest -help -something} {exec} {
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    removeFile error
    if {[string length $err]} {
	set code 1
	append msg \n$err
    }
    return $code
}
test tcltest-2.0 {tcltest (verbose default - 'b')} {unixOrWin} {
    set result [slave msg test.tcl]
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 0 0 1}
test tcltest-2.1 {tcltest -verbose 'b'} {unixOrWin} {
    set result [slave msg test.tcl -verbose 'b']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 0 0 1}
test tcltest-2.2 {tcltest -verbose 'p'} {unixOrWin} {
    set result [slave msg test.tcl -verbose 'p']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 1 0 1}
test tcltest-2.3 {tcltest -verbose 's'} {unixOrWin} {
    set result [slave msg test.tcl -verbose 's']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 0 1 1}
test tcltest-2.4 {tcltest -verbose 'ps'} {unixOrWin} {
    set result [slave msg test.tcl -verbose 'ps']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 1 1 1}
test tcltest-2.5 {tcltest -verbose 'psb'} {unixOrWin} {
    set result [slave msg test.tcl -verbose 'psb']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 1 1}

test tcltest-2.5a {tcltest -verbose 'pass skip body'} {unixOrWin} {
    set result [slave msg test.tcl -verbose "pass skip body"]
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 1 1}

test tcltest-2.6 {tcltest -verbose 't'}  {
    -constraints {unixOrWin}
    -body {
	set result [slave msg test.tcl -verbose 't']
	list $result $msg
    }
    -result {^0 .*a-1.0 start.*b-1.0 start}
    -match regexp
}

test tcltest-2.6a {tcltest -verbose 'start'}  {
    -constraints {unixOrWin}
    -body {
	set result [slave msg test.tcl -verbose start]
	list $result $msg
    }
    -result {^0 .*a-1.0 start.*b-1.0 start}
    -match regexp
}

test tcltest-2.7 {tcltest::verbose}  {
    -body {
	set oldVerbosity [verbose]
	verbose bar
	set currentVerbosity [verbose]
	verbose foo
	set newVerbosity [verbose]
	verbose $oldVerbosity
	list $currentVerbosity $newVerbosity
    }
    -result {body {}}
}

test tcltest-2.8 {tcltest -verbose 'error'} {
    -constraints {unixOrWin}
    -body {
	set result [slave msg test.tcl -verbose error]
	list $result $msg
    }
    -result {errorInfo: foo.*errorCode: 9}
    -match regexp
}
# -match, [match]
test tcltest-3.1 {tcltest -match 'a*'} {unixOrWin} {
    set result [slave msg test.tcl -match a* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 1 0 0 1}
test tcltest-3.2 {tcltest -match 'b*'} {unixOrWin} {
    set result [slave msg test.tcl -match b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+3.+Failed.+1" $msg]
} {0 0 1 0 1}
test tcltest-3.3 {tcltest -match 'c*'} {unixOrWin} {
    set result [slave msg test.tcl -match c* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+4.+Failed.+0" $msg]
} {0 0 0 1 1}
test tcltest-3.4 {tcltest -match 'a* b*'} {unixOrWin} {
    set result [slave msg test.tcl -match {a* b*} -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+2.+Failed.+1" $msg]
} {0 1 1 0 1}

test tcltest-3.5 {tcltest::match}  {
    -body {
	set oldMatch [match]
	match foo
	set currentMatch [match]
	match bar
	set newMatch [match]
	match $oldMatch
	list $currentMatch $newMatch
    }
    -result {foo bar}
}

# -skip, [skip]
test tcltest-4.1 {tcltest -skip 'a*'} {unixOrWin} {
    set result [slave msg test.tcl -skip a* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+2.+Failed.+1" $msg]
} {0 0 1 1 1}
test tcltest-4.2 {tcltest -skip 'b*'} {unixOrWin} {
    set result [slave msg test.tcl -skip b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+2.+Failed.+1" $msg]
} {0 1 0 1 1}
test tcltest-4.3 {tcltest -skip 'c*'} {unixOrWin} {
    set result [slave msg test.tcl -skip c* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 0 1}
test tcltest-4.4 {tcltest -skip 'a* b*'} {unixOrWin} {
    set result [slave msg test.tcl -skip {a* b*} -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+3.+Failed.+1" $msg]
} {0 0 0 1 1}
test tcltest-4.5 {tcltest -match 'a* b*' -skip 'b*'} {unixOrWin} {
    set result [slave msg test.tcl -match {a* b*} -skip b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 1 0 0 1}

test tcltest-4.6 {tcltest::skip} {
    -body {
	set oldSkip [skip]
	skip foo
	set currentSkip [skip]
	skip bar
	set newSkip [skip]
	skip $oldSkip
	list $currentSkip $newSkip
    }
    -result {foo bar}
}

# -constraints, -limitconstraints, [testConstraint],
# $constraintsSpecified, [limitConstraints]
test tcltest-5.1 {tcltest -constraints 'knownBug'} {unixOrWin} {
    set result [slave msg test.tcl -constraints knownBug -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+2.+Skipped.+0.+Failed.+2" $msg]
} {0 1 1 1 1}
test tcltest-5.2 {tcltest -constraints 'knownBug' -limitconstraints 1} {unixOrWin} {
    set result [slave msg test.tcl -constraints knownBug -verbose 'p' -limitconstraints 1]
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 0 0 1 1}

test tcltest-5.3 {testConstraint - constraint empty (tcltest::safeFetch)}  {
    -body {







|





|





|





|





|





|






|







|









|
















|





|








|




|




|




|

















|

|




|




|




|




|




















|




|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    removeFile error
    if {[string length $err]} {
	set code 1
	append msg \n$err
    }
    return $code
}
test tcltest-2.0 {tcltest (verbose default - 'b')} {unixOrPc} {
    set result [slave msg test.tcl]
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 0 0 1}
test tcltest-2.1 {tcltest -verbose 'b'} {unixOrPc} {
    set result [slave msg test.tcl -verbose 'b']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 0 0 1}
test tcltest-2.2 {tcltest -verbose 'p'} {unixOrPc} {
    set result [slave msg test.tcl -verbose 'p']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 1 0 1}
test tcltest-2.3 {tcltest -verbose 's'} {unixOrPc} {
    set result [slave msg test.tcl -verbose 's']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 0 1 1}
test tcltest-2.4 {tcltest -verbose 'ps'} {unixOrPc} {
    set result [slave msg test.tcl -verbose 'ps']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 0 1 1 1}
test tcltest-2.5 {tcltest -verbose 'psb'} {unixOrPc} {
    set result [slave msg test.tcl -verbose 'psb']
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 1 1}

test tcltest-2.5a {tcltest -verbose 'pass skip body'} {unixOrPc} {
    set result [slave msg test.tcl -verbose "pass skip body"]
    list $result [regexp "Contents of test case" $msg] [regexp a-1.0 $msg] \
	    [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 1 1}

test tcltest-2.6 {tcltest -verbose 't'}  {
    -constraints {unixOrPc} 
    -body {
	set result [slave msg test.tcl -verbose 't']
	list $result $msg
    }
    -result {^0 .*a-1.0 start.*b-1.0 start}
    -match regexp
}

test tcltest-2.6a {tcltest -verbose 'start'}  {
    -constraints {unixOrPc} 
    -body {
	set result [slave msg test.tcl -verbose start]
	list $result $msg
    }
    -result {^0 .*a-1.0 start.*b-1.0 start}
    -match regexp
}

test tcltest-2.7 {tcltest::verbose}  {
    -body {
	set oldVerbosity [verbose]
	verbose bar
	set currentVerbosity [verbose]
	verbose foo
	set newVerbosity [verbose]
	verbose $oldVerbosity
	list $currentVerbosity $newVerbosity 
    }
    -result {body {}}
}

test tcltest-2.8 {tcltest -verbose 'error'} {
    -constraints {unixOrPc}
    -body {
	set result [slave msg test.tcl -verbose error]
	list $result $msg
    }
    -result {errorInfo: foo.*errorCode: 9}
    -match regexp
}
# -match, [match]
test tcltest-3.1 {tcltest -match 'a*'} {unixOrPc} {
    set result [slave msg test.tcl -match a* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 1 0 0 1}
test tcltest-3.2 {tcltest -match 'b*'} {unixOrPc} {
    set result [slave msg test.tcl -match b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+3.+Failed.+1" $msg]
} {0 0 1 0 1}
test tcltest-3.3 {tcltest -match 'c*'} {unixOrPc} {
    set result [slave msg test.tcl -match c* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+4.+Failed.+0" $msg]
} {0 0 0 1 1}
test tcltest-3.4 {tcltest -match 'a* b*'} {unixOrPc} {
    set result [slave msg test.tcl -match {a* b*} -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+2.+Failed.+1" $msg]
} {0 1 1 0 1}

test tcltest-3.5 {tcltest::match}  {
    -body {
	set oldMatch [match]
	match foo
	set currentMatch [match]
	match bar
	set newMatch [match]
	match $oldMatch
	list $currentMatch $newMatch
    }
    -result {foo bar}
}
	
# -skip, [skip]
test tcltest-4.1 {tcltest -skip 'a*'} {unixOrPc} {
    set result [slave msg test.tcl -skip a* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+2.+Failed.+1" $msg]
} {0 0 1 1 1}
test tcltest-4.2 {tcltest -skip 'b*'} {unixOrPc} {
    set result [slave msg test.tcl -skip b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+2.+Failed.+1" $msg]
} {0 1 0 1 1}
test tcltest-4.3 {tcltest -skip 'c*'} {unixOrPc} {
    set result [slave msg test.tcl -skip c* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+1.+Failed.+2" $msg]
} {0 1 1 0 1}
test tcltest-4.4 {tcltest -skip 'a* b*'} {unixOrPc} {
    set result [slave msg test.tcl -skip {a* b*} -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+0.+Skipped.+3.+Failed.+1" $msg]
} {0 0 0 1 1}
test tcltest-4.5 {tcltest -match 'a* b*' -skip 'b*'} {unixOrPc} {
    set result [slave msg test.tcl -match {a* b*} -skip b* -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 1 0 0 1}

test tcltest-4.6 {tcltest::skip} {
    -body {
	set oldSkip [skip]
	skip foo
	set currentSkip [skip]
	skip bar
	set newSkip [skip]
	skip $oldSkip
	list $currentSkip $newSkip
    }
    -result {foo bar}
}

# -constraints, -limitconstraints, [testConstraint],
# $constraintsSpecified, [limitConstraints]
test tcltest-5.1 {tcltest -constraints 'knownBug'} {unixOrPc} {
    set result [slave msg test.tcl -constraints knownBug -verbose 'ps']
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+2.+Skipped.+0.+Failed.+2" $msg]
} {0 1 1 1 1}
test tcltest-5.2 {tcltest -constraints 'knownBug' -limitconstraints 1} {unixOrPc} {
    set result [slave msg test.tcl -constraints knownBug -verbose 'p' -limitconstraints 1]
    list $result [regexp a-1.0 $msg] [regexp b-1.0 $msg] [regexp c-1.0 $msg] \
	    [regexp "Total.+4.+Passed.+1.+Skipped.+3.+Failed.+0" $msg]
} {0 0 0 1 1}

test tcltest-5.3 {testConstraint - constraint empty (tcltest::safeFetch)}  {
    -body {
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#	testConstraint tcltestFakeConstraint2 1
#	set r3 $::tcltest::constraintsSpecified
#	list $r1 $r2 $r3
#    }
#    -result {{} tcltestFakeConstraint1 {tcltestFakeConstraint1 tcltestFakeConstraint2}}
#    -cleanup {
#	set ::tcltest::constraintsSpecified $constraintlist
#	unset ::tcltest::testConstraints(tcltestFakeConstraint1)
#	unset ::tcltest::testConstraints(tcltestFakeConstraint2)
#    }
#}

test tcltest-5.5 {InitConstraints: list of built-in constraints} \
	-constraints {!singleTestInterp} \
	-setup {tcltest::InitConstraints} \
	-body { lsort [array names ::tcltest::testConstraints] } \







|
|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#	testConstraint tcltestFakeConstraint2 1
#	set r3 $::tcltest::constraintsSpecified
#	list $r1 $r2 $r3
#    }
#    -result {{} tcltestFakeConstraint1 {tcltestFakeConstraint1 tcltestFakeConstraint2}}
#    -cleanup {
#	set ::tcltest::constraintsSpecified $constraintlist
#	unset ::tcltest::testConstraints(tcltestFakeConstraint1) 
#	unset ::tcltest::testConstraints(tcltestFakeConstraint2) 
#    }
#}

test tcltest-5.5 {InitConstraints: list of built-in constraints} \
	-constraints {!singleTestInterp} \
	-setup {tcltest::InitConstraints} \
	-body { lsort [array names ::tcltest::testConstraints] } \
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
    puts [outputChannel] "a test"
    ::tcltest::PrintError "a really short string"
    ::tcltest::PrintError "a really really really really really really long \
	    string containing \"quotes\" and other bad bad stuff"
    ::tcltest::PrintError "a really really long string containing a \
	    \"Path/that/is/really/long/and/contains/no/spaces\""
    ::tcltest::PrintError "a really really long string containing a \
	    \"Really/Long/Path/that/contains/no/spaces/and/is/longer/than/eighty/characters/to/see/what/happens\""
    ::tcltest::PrintError "Problem renaming file: error renaming \"Z:/ws/tcl8.2/win32-ix86/tests/core\" to \"Z:/ws/tcl8.2/win32-ix86/tests/movecore-core\""
    exit
} printerror.tcl]

test tcltest-6.1 {tcltest -outfile, -errfile defaults} {
    -constraints unixOrWin
    -body {
	slave msg $printerror
	return $msg
    }
    -result {a test.*a really}
    -match regexp
}
test tcltest-6.2 {tcltest -outfile a.tmp} {unixOrWin unixExecs} {
    slave msg $printerror -outfile a.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" a.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 [file exists a.tmp] [file delete a.tmp]
} {0 1 0 1 1 {}}
test tcltest-6.3 {tcltest -errfile a.tmp} {unixOrWin unixExecs} {
    slave msg $printerror -errfile a.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" a.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 [file exists a.tmp] [file delete a.tmp]
} {1 0 1 0 1 {}}
test tcltest-6.4 {tcltest -outfile a.tmp -errfile b.tmp} {unixOrWin unixExecs} {
    slave msg $printerror -outfile a.tmp -errfile b.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" b.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 \
	    [file exists a.tmp] [file delete a.tmp] \
	    [file exists b.tmp] [file delete b.tmp]







|





|







|




|

|






|







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    puts [outputChannel] "a test"
    ::tcltest::PrintError "a really short string"
    ::tcltest::PrintError "a really really really really really really long \
	    string containing \"quotes\" and other bad bad stuff"
    ::tcltest::PrintError "a really really long string containing a \
	    \"Path/that/is/really/long/and/contains/no/spaces\""
    ::tcltest::PrintError "a really really long string containing a \
	    \"Really/Long/Path/that/contains/no/spaces/and/is/longer/than/eighty/characters/to/see/what/happens\"" 
    ::tcltest::PrintError "Problem renaming file: error renaming \"Z:/ws/tcl8.2/win32-ix86/tests/core\" to \"Z:/ws/tcl8.2/win32-ix86/tests/movecore-core\""
    exit
} printerror.tcl]

test tcltest-6.1 {tcltest -outfile, -errfile defaults} {
    -constraints unixOrPc
    -body {
	slave msg $printerror
	return $msg
    }
    -result {a test.*a really}
    -match regexp
}
test tcltest-6.2 {tcltest -outfile a.tmp} {unixOrPc unixExecs} {
    slave msg $printerror -outfile a.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" a.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 [file exists a.tmp] [file delete a.tmp] 
} {0 1 0 1 1 {}}
test tcltest-6.3 {tcltest -errfile a.tmp} {unixOrPc unixExecs} {
    slave msg $printerror -errfile a.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" a.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 [file exists a.tmp] [file delete a.tmp]
} {1 0 1 0 1 {}}
test tcltest-6.4 {tcltest -outfile a.tmp -errfile b.tmp} {unixOrPc unixExecs} {
    slave msg $printerror -outfile a.tmp -errfile b.tmp
    set result1 [catch {exec grep "a test" a.tmp}]
    set result2 [catch {exec grep "a really" b.tmp}]
    list [regexp "a test" $msg] [regexp "a really" $msg] \
	    $result1 $result2 \
	    [file exists a.tmp] [file delete a.tmp] \
	    [file exists b.tmp] [file delete b.tmp]
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
    }
    -body {
	set f0 [errorChannel]
	set f1 [errorFile]
	set f2 [errorFile $ef]
	set f3 [errorChannel]
	set f4 [errorFile]
	subst {$f0;$f1;$f2;$f3;$f4}
    }
    -result {stderr;stderr;.*efile;file[0-9a-f]+;.*efile}
    -match regexp
    -cleanup {
	errorFile $of
	removeFile efile
    }







|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    }
    -body {
	set f0 [errorChannel]
	set f1 [errorFile]
	set f2 [errorFile $ef]
	set f3 [errorChannel]
	set f4 [errorFile]
	subst {$f0;$f1;$f2;$f3;$f4} 
    }
    -result {stderr;stderr;.*efile;file[0-9a-f]+;.*efile}
    -match regexp
    -cleanup {
	errorFile $of
	removeFile efile
    }
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    }
    -body {
	set f0 [outputChannel]
	set f1 [outputFile]
	set f2 [outputFile $ef]
	set f3 [outputChannel]
	set f4 [outputFile]
	subst {$f0;$f1;$f2;$f3;$f4}
    }
    -result {stdout;stdout;.*efile;file[0-9a-f]+;.*efile}
    -match regexp
    -cleanup {
	outputFile $of
	removeFile efile
    }
}

# -debug, [debug]
# Must use child processes to test -debug because it always writes
# messages to stdout, and we have no way to capture stdout of a
# slave interp
test tcltest-7.1 {tcltest test.tcl -debug 0} {unixOrWin} {
    catch {exec [interpreter] test.tcl -debug 0} msg
    regexp "Flags passed into tcltest" $msg
} {0}
test tcltest-7.2 {tcltest test.tcl -debug 1} {unixOrWin} {
    catch {exec [interpreter] test.tcl -debug 1 -skip b*} msg
    list [regexp userSpecifiedSkip $msg] \
	    [regexp "Flags passed into tcltest" $msg]
} {1 0}
test tcltest-7.3 {tcltest test.tcl -debug 1} {unixOrWin} {
    catch {exec [interpreter] test.tcl -debug 1 -match b*} msg
    list [regexp userSpecifiedNonMatch $msg] \
	    [regexp "Flags passed into tcltest" $msg]
} {1 0}
test tcltest-7.4 {tcltest test.tcl -debug 2} {unixOrWin} {
    catch {exec [interpreter] test.tcl -debug 2} msg
    list [regexp "Flags passed into tcltest" $msg] [regexp "Running" $msg]
} {1 0}
test tcltest-7.5 {tcltest test.tcl -debug 3} {unixOrWin} {
    catch {exec [interpreter] test.tcl -debug 3} msg
    list [regexp "Flags passed into tcltest" $msg] [regexp "Running" $msg]
} {1 1}

test tcltest-7.6 {tcltest::debug} {
    -setup {
	set old $::tcltest::debug







|













|



|




|




|



|







445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
    }
    -body {
	set f0 [outputChannel]
	set f1 [outputFile]
	set f2 [outputFile $ef]
	set f3 [outputChannel]
	set f4 [outputFile]
	subst {$f0;$f1;$f2;$f3;$f4} 
    }
    -result {stdout;stdout;.*efile;file[0-9a-f]+;.*efile}
    -match regexp
    -cleanup {
	outputFile $of
	removeFile efile
    }
}

# -debug, [debug]
# Must use child processes to test -debug because it always writes
# messages to stdout, and we have no way to capture stdout of a
# slave interp
test tcltest-7.1 {tcltest test.tcl -debug 0} {unixOrPc} {
    catch {exec [interpreter] test.tcl -debug 0} msg
    regexp "Flags passed into tcltest" $msg
} {0}
test tcltest-7.2 {tcltest test.tcl -debug 1} {unixOrPc} {
    catch {exec [interpreter] test.tcl -debug 1 -skip b*} msg
    list [regexp userSpecifiedSkip $msg] \
	    [regexp "Flags passed into tcltest" $msg]
} {1 0}
test tcltest-7.3 {tcltest test.tcl -debug 1} {unixOrPc} {
    catch {exec [interpreter] test.tcl -debug 1 -match b*} msg
    list [regexp userSpecifiedNonMatch $msg] \
	    [regexp "Flags passed into tcltest" $msg]
} {1 0}
test tcltest-7.4 {tcltest test.tcl -debug 2} {unixOrPc} {
    catch {exec [interpreter] test.tcl -debug 2} msg
    list [regexp "Flags passed into tcltest" $msg] [regexp "Running" $msg]
} {1 0}
test tcltest-7.5 {tcltest test.tcl -debug 3} {unixOrPc} {
    catch {exec [interpreter] test.tcl -debug 3} msg
    list [regexp "Flags passed into tcltest" $msg] [regexp "Running" $msg]
} {1 1}

test tcltest-7.6 {tcltest::debug} {
    -setup {
	set old $::tcltest::debug
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

set tdiaf [makeFile {} thisdirectoryisafile]

set normaldirectory [makeDirectory normaldirectory]
normalizePath normaldirectory

# -tmpdir, [temporaryDirectory]
test tcltest-8.1 {tcltest a.tcl -tmpdir a} -constraints unixOrWin -setup {
    file delete -force thisdirectorydoesnotexist
} -body {
    slave msg $a -tmpdir thisdirectorydoesnotexist
    file exists [file join thisdirectorydoesnotexist a.tmp]
} -cleanup {
    file delete -force thisdirectorydoesnotexist
} -result 1
test tcltest-8.2 {tcltest a.tcl -tmpdir thisdirectoryisafile} {
    -constraints unixOrWin
    -body {
	slave msg $a -tmpdir $tdiaf
	return $msg
    }
    -result {*not a directory*}
    -match glob
}







|








|







517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

set tdiaf [makeFile {} thisdirectoryisafile]

set normaldirectory [makeDirectory normaldirectory]
normalizePath normaldirectory

# -tmpdir, [temporaryDirectory]
test tcltest-8.1 {tcltest a.tcl -tmpdir a} -constraints unixOrPc -setup {
    file delete -force thisdirectorydoesnotexist
} -body {
    slave msg $a -tmpdir thisdirectorydoesnotexist
    file exists [file join thisdirectorydoesnotexist a.tmp]
} -cleanup {
    file delete -force thisdirectorydoesnotexist
} -result 1
test tcltest-8.2 {tcltest a.tcl -tmpdir thisdirectoryisafile} {
    -constraints unixOrPc
    -body {
	slave msg $a -tmpdir $tdiaf
	return $msg
    }
    -result {*not a directory*}
    -match glob
}
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
# interfere with tcltest-5.5
testConstraint notFAT [expr {
       ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWriteableDir] 1]]
    || $::tcl_platform(platform) eq "unix" || [llength [info commands testchmod]]
}]
# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used
test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
    -constraints {unixOrWin notRoot notFAT}
    -body {
	slave msg $a -tmpdir $notWriteableDir
	return $msg
    }
    -result {*not writeable*}
    -match glob
}
test tcltest-8.5 {tcltest a.tcl -tmpdir normaldirectory} {
    -constraints unixOrWin
    -body {
	slave msg $a -tmpdir $normaldirectory
	# The join is necessary because the message can be split on multiple
	# lines
	file exists [file join $normaldirectory a.tmp]
    }
    -cleanup {







|








|







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# interfere with tcltest-5.5
testConstraint notFAT [expr {
       ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWriteableDir] 1]]
    || $::tcl_platform(platform) eq "unix" || [llength [info commands testchmod]]
}]
# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used
test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
    -constraints {unixOrPc notRoot notFAT}
    -body {
	slave msg $a -tmpdir $notWriteableDir
	return $msg
    }
    -result {*not writeable*}
    -match glob
}
test tcltest-8.5 {tcltest a.tcl -tmpdir normaldirectory} {
    -constraints unixOrPc
    -body {
	slave msg $a -tmpdir $normaldirectory
	# The join is necessary because the message can be split on multiple
	# lines
	file exists [file join $normaldirectory a.tmp]
    }
    -cleanup {
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
    list $f1 $f2 $f3
} -cleanup {
    set ::tcltest::temporaryDirectory $old
} -result [list $normaldirectory [workingDirectory] [workingDirectory]]
cd [temporaryDirectory]
# -testdir, [testsDirectory]
test tcltest-8.10 {tcltest a.tcl -testdir thisdirectorydoesnotexist} {
    -constraints unixOrWin
    -setup {
	file delete -force thisdirectorydoesnotexist
    }
    -body {
	slave msg $a -testdir thisdirectorydoesnotexist
	return $msg
    }
    -match glob
    -result {*does not exist*}
}
test tcltest-8.11 {tcltest a.tcl -testdir thisdirectoryisafile} {
    -constraints unixOrWin
    -body {
	slave msg $a -testdir $tdiaf
	return $msg
    }
    -match glob
    -result {*not a directory*}
}
test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {
    -constraints {unix notRoot}
    -body {
	slave msg $a -testdir $notReadableDir
	return $msg
    }
    -match glob
    -result {*not readable*}
}
test tcltest-8.13 {tcltest a.tcl -testdir normaldirectory} {
    -constraints unixOrWin
    -body {
	slave msg $a -testdir $normaldirectory
	# The join is necessary because the message can be split on multiple
	# lines
	list [string first "testdir: $normaldirectory" [join $msg]] \
	    [file exists [file join [temporaryDirectory] a.tmp]]
    }







|











|

















|







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
    list $f1 $f2 $f3
} -cleanup {
    set ::tcltest::temporaryDirectory $old
} -result [list $normaldirectory [workingDirectory] [workingDirectory]]
cd [temporaryDirectory]
# -testdir, [testsDirectory]
test tcltest-8.10 {tcltest a.tcl -testdir thisdirectorydoesnotexist} {
    -constraints unixOrPc
    -setup {
	file delete -force thisdirectorydoesnotexist
    }
    -body {
	slave msg $a -testdir thisdirectorydoesnotexist
	return $msg
    }
    -match glob
    -result {*does not exist*}
}
test tcltest-8.11 {tcltest a.tcl -testdir thisdirectoryisafile} {
    -constraints unixOrPc
    -body {
	slave msg $a -testdir $tdiaf
	return $msg
    }
    -match glob
    -result {*not a directory*}
}
test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {
    -constraints {unix notRoot}
    -body {
	slave msg $a -testdir $notReadableDir
	return $msg
    }
    -match glob
    -result {*not readable*}
}
test tcltest-8.13 {tcltest a.tcl -testdir normaldirectory} {
    -constraints unixOrPc
    -body {
	slave msg $a -testdir $normaldirectory
	# The join is necessary because the message can be split on multiple
	# lines
	list [string first "testdir: $normaldirectory" [join $msg]] \
	    [file exists [file join [temporaryDirectory] a.tmp]]
    }
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 777
	file attributes $notWriteableDir -permissions 777
    }
    default {
	catch {testchmod 0o777 $notWriteableDir}
	catch {file attributes $notWriteableDir -readonly 0}
    }
}

file delete -force -- $notReadableDir $notWriteableDir
removeFile a.tcl
removeFile thisdirectoryisafile
removeDirectory normaldirectory

# -file, -notfile, [matchFiles], [skipFiles]
test tcltest-9.1 {-file d*.tcl} -constraints {unixOrWin} -setup {
    set old [testsDirectory]
    testsDirectory [file dirname [info script]]
} -body {
    slave msg [file join [testsDirectory] all.tcl] -file d*.test
    return $msg
} -cleanup {
    testsDirectory $old
} -match regexp -result {dstring\.test}

test tcltest-9.2 {-file d*.tcl} -constraints {unixOrWin} -setup {
    set old [testsDirectory]
    testsDirectory [file dirname [info script]]
} -body {
    slave msg [file join [testsDirectory] all.tcl] \
	    -file d*.test -notfile dstring*
    regexp {dstring\.test} $msg
} -cleanup {
    testsDirectory $old
} -result 0

test tcltest-9.3 {matchFiles}  {
    -body {
	set old [matchFiles]
	matchFiles foo
	set current [matchFiles]
	matchFiles bar
	set new [matchFiles]
	matchFiles $old
	list $current $new
    }
    -result {foo bar}
}

test tcltest-9.4 {skipFiles} {
    -body {
	set old [skipFiles]
	skipFiles foo
	set current [skipFiles]
	skipFiles bar
	set new [skipFiles]
	skipFiles $old
	list $current $new
    }
    -result {foo bar}
}

test tcltest-9.5 {GetMatchingFiles: Bug 1119798} -setup {
    set d [makeDirectory tmp]
    makeDirectory foo $d
    makeFile {} fee $d







|










|









|



















|












|







715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 777
	file attributes $notWriteableDir -permissions 777
    }
    default {
	catch {testchmod 777 $notWriteableDir}
	catch {file attributes $notWriteableDir -readonly 0}
    }
}

file delete -force -- $notReadableDir $notWriteableDir
removeFile a.tcl
removeFile thisdirectoryisafile
removeDirectory normaldirectory

# -file, -notfile, [matchFiles], [skipFiles]
test tcltest-9.1 {-file d*.tcl} -constraints {unixOrPc} -setup {
    set old [testsDirectory]
    testsDirectory [file dirname [info script]]
} -body {
    slave msg [file join [testsDirectory] all.tcl] -file d*.test
    return $msg
} -cleanup {
    testsDirectory $old
} -match regexp -result {dstring\.test}

test tcltest-9.2 {-file d*.tcl} -constraints {unixOrPc} -setup {
    set old [testsDirectory]
    testsDirectory [file dirname [info script]]
} -body {
    slave msg [file join [testsDirectory] all.tcl] \
	    -file d*.test -notfile dstring*
    regexp {dstring\.test} $msg
} -cleanup {
    testsDirectory $old
} -result 0

test tcltest-9.3 {matchFiles}  {
    -body {
	set old [matchFiles]
	matchFiles foo
	set current [matchFiles]
	matchFiles bar
	set new [matchFiles]
	matchFiles $old
	list $current $new
    } 
    -result {foo bar}
}

test tcltest-9.4 {skipFiles} {
    -body {
	set old [skipFiles]
	skipFiles foo
	set current [skipFiles]
	skipFiles bar
	set new [skipFiles]
	skipFiles $old
	list $current $new
    } 
    -result {foo bar}
}

test tcltest-9.5 {GetMatchingFiles: Bug 1119798} -setup {
    set d [makeDirectory tmp]
    makeDirectory foo $d
    makeFile {} fee $d
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
	close $f
    } {}
    ::tcltest::cleanupTests
    return
} makecore.tcl]

cd [temporaryDirectory]
test tcltest-10.1 {-preservecore 0} {unixOrWin} {
    slave msg $mc -preservecore 0
    file delete core
    regexp "Core file produced" $msg
} {0}
test tcltest-10.2 {-preservecore 1} {unixOrWin} {
    slave msg $mc -preservecore 1
    file delete core
    regexp "Core file produced" $msg
} {1}
test tcltest-10.3 {-preservecore 2} {unixOrWin} {
    slave msg $mc -preservecore 2
    file delete core
    list [regexp "Core file produced" $msg] [regexp "Moving file to" $msg] \
	    [regexp "core-" $msg] [file delete core-makecore]
} {1 1 1 {}}
test tcltest-10.4 {-preservecore 3} {unixOrWin} {
    slave msg $mc -preservecore 3
    file delete core
    list [regexp "Core file produced" $msg] [regexp "Moving file to" $msg] \
	    [regexp "core-" $msg] [file delete core-makecore]
} {1 1 1 {}}

# Removing this test.  It makes no sense to test the ability of







|




|




|





|







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
	close $f
    } {}
    ::tcltest::cleanupTests
    return
} makecore.tcl]

cd [temporaryDirectory]
test tcltest-10.1 {-preservecore 0} {unixOrPc} {
    slave msg $mc -preservecore 0
    file delete core
    regexp "Core file produced" $msg
} {0}
test tcltest-10.2 {-preservecore 1} {unixOrPc} {
    slave msg $mc -preservecore 1
    file delete core
    regexp "Core file produced" $msg
} {1}
test tcltest-10.3 {-preservecore 2} {unixOrPc} {
    slave msg $mc -preservecore 2
    file delete core
    list [regexp "Core file produced" $msg] [regexp "Moving file to" $msg] \
	    [regexp "core-" $msg] [file delete core-makecore]
} {1 1 1 {}}
test tcltest-10.4 {-preservecore 3} {unixOrPc} {
    slave msg $mc -preservecore 3
    file delete core
    list [regexp "Core file produced" $msg] [regexp "Moving file to" $msg] \
	    [regexp "core-" $msg] [file delete core-makecore]
} {1 1 1 {}}

# Removing this test.  It makes no sense to test the ability of
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
    package require tcltest
    namespace import tcltest::*
    puts [outputChannel] $::tcltest::loadScript
    exit
}
set loadfile [makeFile $contents load.tcl]

test tcltest-12.1 {-load xxx} {unixOrWin} {
    slave msg $loadfile -load xxx
    return $msg
} {xxx}

# Using child process because of -debug usage.
test tcltest-12.2 {-loadfile load.tcl} {unixOrWin} {
    catch {exec [interpreter] $loadfile -debug 2 -loadfile $loadfile} msg
    list \
	    [regexp {tcltest} [join [list $msg] [split $msg \n]]] \
	    [regexp {loadScript} [join [list $msg] [split $msg \n]]]
} {1 1}

test tcltest-12.3 {loadScript} {







|





|







848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
    package require tcltest
    namespace import tcltest::*
    puts [outputChannel] $::tcltest::loadScript
    exit
}
set loadfile [makeFile $contents load.tcl]

test tcltest-12.1 {-load xxx} {unixOrPc} {
    slave msg $loadfile -load xxx
    return $msg
} {xxx}

# Using child process because of -debug usage.
test tcltest-12.2 {-loadfile load.tcl} {unixOrPc} {
    catch {exec [interpreter] $loadfile -debug 2 -loadfile $loadfile} msg
    list \
	    [regexp {tcltest} [join [list $msg] [split $msg \n]]] \
	    [regexp {loadScript} [join [list $msg] [split $msg \n]]]
} {1 1}

test tcltest-12.3 {loadScript} {
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
	set ::tcltest::loadFile $oldf
    }
}
removeFile load.tcl

# [interpreter]
test tcltest-13.1 {interpreter} {
    -constraints notValgrind
    -setup {
	#to do:  Why is $::tcltest::tcltest being saved and restored here?
	set old $::tcltest::tcltest
	set ::tcltest::tcltest tcltest
    }
    -body {
	set f1 [interpreter]
	set f2 [interpreter tclsh]
	set f3 [interpreter]
	list $f1 $f2 $f3
    }
    -result {tcltest tclsh tclsh}
    -cleanup {
	# writing ::tcltest::tcltest triggers a trace that sets up the stdio
	# constraint, which involves a call to [exec] that might fail after
	# "fork" and before "exec", in which case the forked process will not
	# have a chance to clean itself up before exiting, which causes
	# valgrind to issue numerous "still reachable" reports.
	set ::tcltest::tcltest $old
    }
}

# -singleproc, [singleProcess]
set spd [makeDirectory singleprocdir]
makeFile {







<

<











<
<
<
<
<







903
904
905
906
907
908
909

910

911
912
913
914
915
916
917
918
919
920
921





922
923
924
925
926
927
928
	set ::tcltest::loadFile $oldf
    }
}
removeFile load.tcl

# [interpreter]
test tcltest-13.1 {interpreter} {

    -setup {

	set old $::tcltest::tcltest
	set ::tcltest::tcltest tcltest
    }
    -body {
	set f1 [interpreter]
	set f2 [interpreter tclsh]
	set f3 [interpreter]
	list $f1 $f2 $f3
    }
    -result {tcltest tclsh tclsh}
    -cleanup {





	set ::tcltest::tcltest $old
    }
}

# -singleproc, [singleProcess]
set spd [makeDirectory singleprocdir]
makeFile {
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
    namespace import tcltest::*
    testsDirectory [file join [temporaryDirectory] singleprocdir]
    runAllTests
} all-single.tcl $spd]
cd [workingDirectory]

test tcltest-14.1 {-singleproc - single process} {
    -constraints {unixOrWin}
    -body {
	slave msg $allfile -singleproc 0 -tmpdir [temporaryDirectory]
	return $msg
    }
    -result {Test file error: can't unset .foo.: no such variable}
    -match regexp
}

test tcltest-14.2 {-singleproc - multiple process} {
    -constraints {unixOrWin}
    -body {
	slave msg $allfile -singleproc 1 -tmpdir [temporaryDirectory]
	return $msg
    }
    -result {single1.test.*single2.test.*all\-single.tcl:.*Total.*0.*Passed.*0.*Skipped.*0.*Failed.*0}
    -match regexp
}







|









|







938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
    namespace import tcltest::*
    testsDirectory [file join [temporaryDirectory] singleprocdir]
    runAllTests
} all-single.tcl $spd]
cd [workingDirectory]

test tcltest-14.1 {-singleproc - single process} {
    -constraints {unixOrPc}
    -body {
	slave msg $allfile -singleproc 0 -tmpdir [temporaryDirectory]
	return $msg
    }
    -result {Test file error: can't unset .foo.: no such variable}
    -match regexp
}

test tcltest-14.2 {-singleproc - multiple process} {
    -constraints {unixOrPc}
    -body {
	slave msg $allfile -singleproc 1 -tmpdir [temporaryDirectory]
	return $msg
    }
    -result {single1.test.*single2.test.*all\-single.tcl:.*Total.*0.*Passed.*0.*Skipped.*0.*Failed.*0}
    -match regexp
}
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
    package require tcltest
    namespace import -force tcltest::*
    testsDirectory [file join [temporaryDirectory] dirtestdir dirtestdir2.3]
    runAllTests
} all.tcl $dtd3

test tcltest-15.1 {basic directory walking} {
    -constraints {unixOrWin}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -match regexp
    -returnCodes 1
    -result {Tests located in:.*dirtestdir.*Tests located in:.*dirtestdir2.[123].*Tests located in:.*dirtestdir2.[123].*Tests located in:.*dirtestdir2.[123]}
}

test tcltest-15.2 {-asidefromdir} {
    -constraints {unixOrWin}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-asidefromdir dirtestdir2.3 \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -match regexp
    -returnCodes 1
    -result {Tests located in:.*dirtestdir.*Tests located in:.*dirtestdir2.[12].*Tests located in:.*dirtestdir2.[12].*dirtestdir2.[12] test ended at .*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error:  No test files remain after applying your match and skip patterns!
Error:  No test files remain after applying your match and skip patterns!
Error:  No test files remain after applying your match and skip patterns!$}
}

test tcltest-15.3 {-relateddir, non-existent dir} {
    -constraints {unixOrWin}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir [file join [temporaryDirectory] dirtestdir0] \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -returnCodes 1
    -match regexp
    -result {[^~]|dirtestdir[^2]}
}

test tcltest-15.4 {-relateddir, subdir} {
    -constraints {unixOrWin}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir dirtestdir2.1 -tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -returnCodes 1
    -match regexp
    -result {Tests located in:.*dirtestdir2.[^23]}
}
test tcltest-15.5 {-relateddir, -asidefromdir} {
    -constraints {unixOrWin}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir "dirtestdir2.1 dirtestdir2.2" \
		-asidefromdir dirtestdir2.2 \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg







|













|

















|














|












|







1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
    package require tcltest
    namespace import -force tcltest::*
    testsDirectory [file join [temporaryDirectory] dirtestdir dirtestdir2.3]
    runAllTests
} all.tcl $dtd3

test tcltest-15.1 {basic directory walking} {
    -constraints {unixOrPc}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -match regexp
    -returnCodes 1
    -result {Tests located in:.*dirtestdir.*Tests located in:.*dirtestdir2.[123].*Tests located in:.*dirtestdir2.[123].*Tests located in:.*dirtestdir2.[123]}
}

test tcltest-15.2 {-asidefromdir} {
    -constraints {unixOrPc}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-asidefromdir dirtestdir2.3 \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -match regexp
    -returnCodes 1
    -result {Tests located in:.*dirtestdir.*Tests located in:.*dirtestdir2.[12].*Tests located in:.*dirtestdir2.[12].*dirtestdir2.[12] test ended at .*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error:  No test files remain after applying your match and skip patterns!
Error:  No test files remain after applying your match and skip patterns!
Error:  No test files remain after applying your match and skip patterns!$}
}

test tcltest-15.3 {-relateddir, non-existent dir} {
    -constraints {unixOrPc}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir [file join [temporaryDirectory] dirtestdir0] \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -returnCodes 1
    -match regexp
    -result {[^~]|dirtestdir[^2]}
}

test tcltest-15.4 {-relateddir, subdir} {
    -constraints {unixOrPc}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir dirtestdir2.1 -tmpdir [temporaryDirectory]] == 1} {
	    error $msg
	}
    }
    -returnCodes 1
    -match regexp
    -result {Tests located in:.*dirtestdir2.[^23]}
}
test tcltest-15.5 {-relateddir, -asidefromdir} {
    -constraints {unixOrPc}
    -body {
	if {[slave msg \
		[file join $dtd all.tcl] \
		-relateddir "dirtestdir2.1 dirtestdir2.2" \
		-asidefromdir dirtestdir2.2 \
		-tmpdir [temporaryDirectory]] == 1} {
	    error $msg
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
	slave1 alias puts puts
	interp create slave2
	slave2 alias puts puts
    } -cleanup {
	interp delete slave2
	interp delete slave1
	if {$oldoptions eq "none"} {
	    unset ::env(TCLTEST_OPTIONS)
	} else {
	    set ::env(TCLTEST_OPTIONS) $oldoptions
	}
    } -body {
	slave1 eval [package ifneeded tcltest [package provide tcltest]]
	slave1 eval tcltest::debug
	set ::env(TCLTEST_OPTIONS) "-debug 3"
	slave2 eval [package ifneeded tcltest [package provide tcltest]]
	slave2 eval tcltest::debug
    } -result {^3$} -match regexp -output\
{tcltest::debug\s+= 2.*tcltest::debug\s+= 3}

# Begin testing of tcltest procs ...

cd [temporaryDirectory]
# PrintError
test tcltest-20.1 {PrintError} {unixOrWin} {
    set result [slave msg $printerror]
    list $result [regexp "Error:  a really short string" $msg] \
	    [regexp "     \"quotes\"" $msg] [regexp "    \"Path" $msg] \
	    [regexp "    \"Really" $msg] [regexp Problem $msg]
} {1 1 1 1 1 1}
cd [workingDirectory]
removeFile printerror.tcl







|
















|







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
	slave1 alias puts puts
	interp create slave2
	slave2 alias puts puts
    } -cleanup {
	interp delete slave2
	interp delete slave1
	if {$oldoptions eq "none"} {
	    unset ::env(TCLTEST_OPTIONS) 
	} else {
	    set ::env(TCLTEST_OPTIONS) $oldoptions
	}
    } -body {
	slave1 eval [package ifneeded tcltest [package provide tcltest]]
	slave1 eval tcltest::debug
	set ::env(TCLTEST_OPTIONS) "-debug 3"
	slave2 eval [package ifneeded tcltest [package provide tcltest]]
	slave2 eval tcltest::debug
    } -result {^3$} -match regexp -output\
{tcltest::debug\s+= 2.*tcltest::debug\s+= 3}

# Begin testing of tcltest procs ...

cd [temporaryDirectory]
# PrintError
test tcltest-20.1 {PrintError} {unixOrPc} {
    set result [slave msg $printerror]
    list $result [regexp "Error:  a really short string" $msg] \
	    [regexp "     \"quotes\"" $msg] [regexp "    \"Path" $msg] \
	    [regexp "    \"Really" $msg] [regexp Problem $msg]
} {1 1 1 1 1 1}
cd [workingDirectory]
removeFile printerror.tcl
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
test tcltest-21.2 {force a test command failure} {
    -body {
	test tcltest-21.2.0 {
	    return 2
	} {1}
    }
    -returnCodes 1
    -result {bad option "1": must be -body, -cleanup, -constraints, -errorCode, -errorOutput, -match, -output, -result, -returnCodes, or -setup}
}

test tcltest-21.3 {test command with setup} {
    -setup {
	set foo 1
    }
    -body {







|







1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
test tcltest-21.2 {force a test command failure} {
    -body {
	test tcltest-21.2.0 {
	    return 2
	} {1}
    }
    -returnCodes 1
    -result {bad option "1": must be -body, -cleanup, -constraints, -errorOutput, -match, -output, -result, -returnCodes, or -setup}
}

test tcltest-21.3 {test command with setup} {
    -setup {
	set foo 1
    }
    -body {
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
	test tcltest-21.6.0 {foo-3} {
	    -setup {
		if {[info exists foo]} {
		    unset foo
		}
		set foo 1
		set expected 2
	    }
	    -body {
		incr foo
		set foo
	    }
	    -cleanup {
		if {$foo != 2} {
		    puts [outputChannel] "foo is wrong"







|







1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
	test tcltest-21.6.0 {foo-3} {
	    -setup {
		if {[info exists foo]} {
		    unset foo
		}
		set foo 1
		set expected 2
	    } 
	    -body {
		incr foo
		set foo
	    }
	    -cleanup {
		if {$foo != 2} {
		    puts [outputChannel] "foo is wrong"
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
    -cleanup {set ::tcltest::currentFailure $fail}
    -body {
	test tcltest-21.7.0 {foo-4} {
	    -foobar {}
	}
    }
    -returnCodes 1
    -result {bad option "-foobar": must be -body, -cleanup, -constraints, -errorCode, -errorOutput, -match, -output, -result, -returnCodes, or -setup}
}

# alternate test command format (these are the same as 21.1-21.6, with the
# exception of being in the all-inline format)

test tcltest-21.7a {expect with glob} \
	-body {list a b c d e} \
	-result {[ab] b c d e} \
	-match glob

test tcltest-21.8 {force a test command failure} \
    -setup {set fail $::tcltest::currentFailure} \
    -body {
        test tcltest-21.8.0 {
            return 2
        } {1}
    } \
    -returnCodes 1 \
    -cleanup {set ::tcltest::currentFailure $fail} \
    -result {bad option "1": must be -body, -cleanup, -constraints, -errorCode, -errorOutput, -match, -output, -result, -returnCodes, or -setup}

test tcltest-21.9 {test command with setup} \
	-setup {set foo 1} \
	-body {set foo} \
	-cleanup {unset foo} \
	-result {1}








|



















|







1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
    -cleanup {set ::tcltest::currentFailure $fail}
    -body {
	test tcltest-21.7.0 {foo-4} {
	    -foobar {}
	}
    }
    -returnCodes 1
    -result {bad option "-foobar": must be -body, -cleanup, -constraints, -errorOutput, -match, -output, -result, -returnCodes, or -setup}
}

# alternate test command format (these are the same as 21.1-21.6, with the
# exception of being in the all-inline format)

test tcltest-21.7a {expect with glob} \
	-body {list a b c d e} \
	-result {[ab] b c d e} \
	-match glob

test tcltest-21.8 {force a test command failure} \
    -setup {set fail $::tcltest::currentFailure} \
    -body {
        test tcltest-21.8.0 {
            return 2
        } {1}
    } \
    -returnCodes 1 \
    -cleanup {set ::tcltest::currentFailure $fail} \
    -result {bad option "1": must be -body, -cleanup, -constraints, -errorOutput, -match, -output, -result, -returnCodes, or -setup}

test tcltest-21.9 {test command with setup} \
	-setup {set foo 1} \
	-body {set foo} \
	-cleanup {unset foo} \
	-result {1}

1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
    }
    cleanupTests
} test.test $atd

# Must use a child process because stdout/stderr parsing can't be
# duplicated in slave interp.
test tcltest-22.1 {runAllTests} {
    -constraints {unixOrWin}
    -body {
	exec [interpreter] \
		[file join $atd all.tcl] \
		-verbose t -tmpdir [temporaryDirectory]
    }
    -match regexp
    -result "Test files exiting with errors:.*error.test.*exit.test"







|







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
    }
    cleanupTests
} test.test $atd

# Must use a child process because stdout/stderr parsing can't be
# duplicated in slave interp.
test tcltest-22.1 {runAllTests} {
    -constraints {unixOrPc}
    -body {
	exec [interpreter] \
		[file join $atd all.tcl] \
		-verbose t -tmpdir [temporaryDirectory]
    }
    -match regexp
    -result "Test files exiting with errors:.*error.test.*exit.test"
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
	makeFile {} t1.tmp
	makeFile {} et1.tmp $mfdir
	list [file exists [file join [temporaryDirectory] t1.tmp]] \
		[file exists [file join $mfdir et1.tmp]]
    }
    -cleanup {
	file delete -force $mfdir \
		[file join [temporaryDirectory] t1.tmp]
    }
    -result {1 1}
}
test tcltest-23.2 {removeFile} {
    -setup {
	set mfdir [file join [temporaryDirectory] mfdir]
	file mkdir $mfdir







|







1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
	makeFile {} t1.tmp
	makeFile {} et1.tmp $mfdir
	list [file exists [file join [temporaryDirectory] t1.tmp]] \
		[file exists [file join $mfdir et1.tmp]]
    }
    -cleanup {
	file delete -force $mfdir \
		[file join [temporaryDirectory] t1.tmp] 
    }
    -result {1 1}
}
test tcltest-23.2 {removeFile} {
    -setup {
	set mfdir [file join [temporaryDirectory] mfdir]
	file mkdir $mfdir
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
	removeFile t1.tmp
	removeFile et1.tmp $mfdir
	list [file exists [file join [temporaryDirectory] t1.tmp]] \
		[file exists [file join $mfdir et1.tmp]]
    }
    -cleanup {
	file delete -force $mfdir \
		[file join [temporaryDirectory] t1.tmp]
    }
    -result {0 0}
}
test tcltest-23.3 {makeDirectory} {
    -body {
	set mfdir [file join [temporaryDirectory] mfdir]
	file mkdir $mfdir







|







1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
	removeFile t1.tmp
	removeFile et1.tmp $mfdir
	list [file exists [file join [temporaryDirectory] t1.tmp]] \
		[file exists [file join $mfdir et1.tmp]]
    }
    -cleanup {
	file delete -force $mfdir \
		[file join [temporaryDirectory] t1.tmp] 
    }
    -result {0 0}
}
test tcltest-23.3 {makeDirectory} {
    -body {
	set mfdir [file join [temporaryDirectory] mfdir]
	file mkdir $mfdir
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
    return $msg
} -cleanup {
    removeFile test.tcl
} -match glob -result {*
---- errorInfo: body error
*
---- errorInfo(cleanup): cleanup error*}

cleanupTests
}

namespace delete ::tcltest::test
return

# Local Variables:
# mode: tcl
# End:







|





<
<
<
<
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834




    return $msg
} -cleanup {
    removeFile test.tcl
} -match glob -result {*
---- errorInfo: body error
*
---- errorInfo(cleanup): cleanup error*}

cleanupTests
}

namespace delete ::tcltest::test
return




Changes to tests/timer.test.

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    set y $x
    after 400
    update
    list $y $x
} {before after}
test timer-6.5 {Tcl_AfterCmd procedure, ms argument} {
    set x before
    after 400 set x after
    after 200
    update
    set y $x
    after 400
    update
    list $y $x
} {before after}
test timer-6.6 {Tcl_AfterCmd procedure, cancel option} {
    list [catch {after cancel} msg] $msg
} {1 {wrong # args: should be "after cancel id|command"}}
test timer-6.7 {Tcl_AfterCmd procedure, cancel option} {







|



|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    set y $x
    after 400
    update
    list $y $x
} {before after}
test timer-6.5 {Tcl_AfterCmd procedure, ms argument} {
    set x before
    after 300 set x after
    after 200
    update
    set y $x
    after 200
    update
    list $y $x
} {before after}
test timer-6.6 {Tcl_AfterCmd procedure, cancel option} {
    list [catch {after cancel} msg] $msg
} {1 {wrong # args: should be "after cancel id|command"}}
test timer-6.7 {Tcl_AfterCmd procedure, cancel option} {

Changes to tests/tm.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
# This file contains tests for the ::tcl::tm::* commands.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 2004 by Donal K. Fellows.
# All rights reserved.

package require Tcl 8.5-
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

test tm-1.1 {tm: path command exists} {
    catch { ::tcl::tm::path }
    info commands ::tcl::tm::path
} ::tcl::tm::path
test tm-1.2 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path foo
} -result {unknown or ambiguous subcommand "foo": must be add, list, or remove}
test tm-1.3 {tm: path command syntax} {
    ::tcl::tm::path add
} {}
test tm-1.4 {tm: path command syntax} {
    ::tcl::tm::path remove
} {}
test tm-1.5 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path list foobar
} -result "wrong # args: should be \"::tcl::tm::path list\""

test tm-2.1 {tm: roots command exists} {
    catch { ::tcl::tm::roots }
    info commands ::tcl::tm::roots








|












|

|
|

|







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
# This file contains tests for the ::tcl::tm::* commands.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 2004 by Donal K. Fellows.
# All rights reserved.

package require Tcl 8.5
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

test tm-1.1 {tm: path command exists} {
    catch { ::tcl::tm::path }
    info commands ::tcl::tm::path
} ::tcl::tm::path
test tm-1.2 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path foo
} -result {unknown or ambiguous subcommand "foo": must be add, list, or remove}
test tm-1.3 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path add
} -result "wrong # args: should be \"::tcl::tm::path add path ...\""
test tm-1.4 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path remove
} -result "wrong # args: should be \"::tcl::tm::path remove path ...\""
test tm-1.5 {tm: path command syntax} -returnCodes error -body {
    ::tcl::tm::path list foobar
} -result "wrong # args: should be \"::tcl::tm::path list\""

test tm-2.1 {tm: roots command exists} {
    catch { ::tcl::tm::roots }
    info commands ::tcl::tm::roots
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    ::tcl::tm::path list
} -result {geode snarf foo}


proc genpaths {base} {
    # Normalizing picks up drive letters on windows [Bug 1053568]
    set base [file normalize $base]
    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    set results {}
    set base [file join $base tcl$major]
    lappend results [file join $base site-tcl]
    for {set i 0} {$i <= $minor} {incr i} {
	lappend results [file join $base ${major}.$i]
    }
    return $results







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    ::tcl::tm::path list
} -result {geode snarf foo}


proc genpaths {base} {
    # Normalizing picks up drive letters on windows [Bug 1053568]
    set base [file normalize $base]
    lassign [split [package present Tcl] .] major minor 
    set results {}
    set base [file join $base tcl$major]
    lappend results [file join $base site-tcl]
    for {set i 0} {$i <= $minor} {incr i} {
	lappend results [file join $base ${major}.$i]
    }
    return $results

Changes to tests/unixInit.test.

345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}
    set enc [gets $f]
    close $f
    unset env(LANG)
    set enc
} -match regexp -result {^(iso8859-15?|utf-8)$}

test unixInit-3.2 {TclpSetInitialEncodings} {unix stdio} {
    set env(LANG) japanese
    catch {set oldlc_all $env(LC_ALL)}
    set env(LC_ALL) japanese
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}







|
>







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}
    set enc [gets $f]
    close $f
    unset env(LANG)
    set enc
} -match regexp -result [expr {
	($tcl_platform(os) eq "Darwin") ? "^utf-8$" : "^iso8859-15?$"}]
test unixInit-3.2 {TclpSetInitialEncodings} {unix stdio} {
    set env(LANG) japanese
    catch {set oldlc_all $env(LC_ALL)}
    set env(LC_ALL) japanese
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}

Changes to tests/unknown.test.

56
57
58
59
60
61
62
63
    list [catch {non-existent a b} msg] $msg $errorCode
} {1 {unknown failed} NONE}

# cleanup
catch {rename unknown {}}
catch {rename unknown.old unknown}
cleanupTests
return







|
56
57
58
59
60
61
62
63
    list [catch {non-existent a b} msg] $msg $errorCode
} {1 {unknown failed} NONE}

# cleanup
catch {rename unknown {}}
catch {rename unknown.old unknown}
cleanupTests
return 

Changes to tests/unload.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Commands covered:  unload
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2003-2004 Georgios Petasis
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*







|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Commands covered:  unload
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2003-2004 by Georgios Petasis
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    set pkgua_loaded {}
    set pkgua_detached {}
    set pkgua_unloaded {}
}
test unload-3.1 {basic loading of non-unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    catch {rename pkgb_sub {}}
    load [file join $testDir pkgb$ext] Pkgb child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
         [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test unload-3.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] Pkgua child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
test unload-3.3 {unloading of a package that has never been loaded from a safe interpreter} \
	[list $dll $loaded] {
    list [catch {unload [file join $testDir pkga$ext] {} child} msg] \







|






|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    set pkgua_loaded {}
    set pkgua_detached {}
    set pkgua_unloaded {}
}
test unload-3.1 {basic loading of non-unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    catch {rename pkgb_sub {}}
    load [file join $testDir pkgb$ext] pKgB child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
         [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test unload-3.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pKgUA child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
test unload-3.3 {unloading of a package that has never been loaded from a safe interpreter} \
	[list $dll $loaded] {
    list [catch {unload [file join $testDir pkga$ext] {} child} msg] \
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{. . .} {} 0 {pkgua_eq pkgua_quote} {.. . .}}
test unload-3.7 {basic unloading of re-loaded package from a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] Pkgua child] \
	    [child eval info commands pkgua_*] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{.. . .} {} {} {.. .. ..}}

# Tests for loading/unloading of a package among multiple interpreters...
interp create child-trusted
child-trusted eval {







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{. . .} {} 0 {pkgua_eq pkgua_quote} {.. . .}}
test unload-3.7 {basic unloading of re-loaded package from a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] pKgUa child] \
	    [child eval info commands pkgua_*] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{.. . .} {} {} {.. .. ..}}

# Tests for loading/unloading of a package among multiple interpreters...
interp create child-trusted
child-trusted eval {
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
	    [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
	    [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
## Load package in child-safe interpreter...
test unload-4.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] Pkgua child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
## Load package in child-trusted interpreter...
test unload-4.3 {basic loading of unloadable package in a second trusted interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] Pkgua child-trusted] \
	    [child-trusted eval pkgua_eq abc def] \
	    [lsort [child-trusted eval info commands pkgua_*]] \
	    [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
## Unload the package from the main trusted interpreter...
test unload-4.4 {basic unloading of unloadable package from trusted interpreter, with guess for package name} \
	[list $dll $loaded] {







|








|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
	    [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
	    [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
## Load package in child-safe interpreter...
test unload-4.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pKgUA child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
## Load package in child-trusted interpreter...
test unload-4.3 {basic loading of unloadable package in a second trusted interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pkguA child-trusted] \
	    [child-trusted eval pkgua_eq abc def] \
	    [lsort [child-trusted eval info commands pkgua_*]] \
	    [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
## Unload the package from the main trusted interpreter...
test unload-4.4 {basic unloading of unloadable package from trusted interpreter, with guess for package name} \
	[list $dll $loaded] {
213
214
215
216
217
218
219
220
221
222
223

# cleanup
interp delete child
interp delete child-trusted
unset ext
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







<
<
<
<
213
214
215
216
217
218
219





# cleanup
interp delete child
interp delete child-trusted
unset ext
::tcltest::cleanupTests
return




Changes to tests/uplevel.test.

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
} 66
test uplevel-3.4 {uplevel to same level} {
    set y zzz
    proc a1 {} {set y 55; uplevel #1 set y}
    a1
} 55

test uplevel-4.0.1 {error: non-existent level} -body {
    uplevel #0 { uplevel { set y 222 } }
} -returnCodes error -result {bad level "1"}
test uplevel-4.0.2 {error: non-existent level} -setup {
    interp create i
} -body {
    i eval { uplevel { set y 222 } }
} -returnCodes error -result {bad level "1"} -cleanup {
    interp delete i
}
test uplevel-4.1 {error: non-existent level} {
    list [catch c1 msg] $msg
} {1 {bad level "#2"}}
test uplevel-4.2 {error: non-existent level} {
    proc c2 {} {uplevel 3 {set a b}}
    list [catch c2 msg] $msg
} {1 {bad level "3"}}







<
<
<
<
<
<
<
<
<
<







79
80
81
82
83
84
85










86
87
88
89
90
91
92
} 66
test uplevel-3.4 {uplevel to same level} {
    set y zzz
    proc a1 {} {set y 55; uplevel #1 set y}
    a1
} 55











test uplevel-4.1 {error: non-existent level} {
    list [catch c1 msg] $msg
} {1 {bad level "#2"}}
test uplevel-4.2 {error: non-existent level} {
    proc c2 {} {uplevel 3 {set a b}}
    list [catch c2 msg] $msg
} {1 {bad level "3"}}

Changes to tests/upvar.test.

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
test upvar-8.2 {errors in upvar command} {
    list [catch {upvar 1} msg] $msg
} {1 {wrong # args: should be "upvar ?level? otherVar localVar ?otherVar localVar ...?"}}
test upvar-8.3 {errors in upvar command} {
    proc p1 {} {upvar a b c}
    list [catch p1 msg] $msg
} {1 {wrong # args: should be "upvar ?level? otherVar localVar ?otherVar localVar ...?"}}
test upvar-8.3.1 {bad level for upvar (upvar at top-level, bug [775ee88560])} -body {
    proc p1 {} { uplevel { upvar b b; lappend b UNEXPECTED } }
    uplevel #0 { p1 }
} -returnCodes error -result {bad level "1"}
test upvar-8.3.2 {bad level for upvar (upvar at top-level, bug [775ee88560])} -setup {
    interp create i
} -body {
    i eval { upvar b b; lappend b UNEXPECTED }
} -returnCodes error -result {bad level "1"} -cleanup {
    interp delete i
}
test upvar-8.4 {errors in upvar command} {
    proc p1 {} {upvar 0 b b}
    list [catch p1 msg] $msg
} {1 {can't upvar from variable to itself}}
test upvar-8.5 {errors in upvar command} {
    proc p1 {} {upvar 0 a b; upvar 0 b a}
    list [catch p1 msg] $msg







<
<
<
<
<
<
<
<
<
<
<







294
295
296
297
298
299
300











301
302
303
304
305
306
307
test upvar-8.2 {errors in upvar command} {
    list [catch {upvar 1} msg] $msg
} {1 {wrong # args: should be "upvar ?level? otherVar localVar ?otherVar localVar ...?"}}
test upvar-8.3 {errors in upvar command} {
    proc p1 {} {upvar a b c}
    list [catch p1 msg] $msg
} {1 {wrong # args: should be "upvar ?level? otherVar localVar ?otherVar localVar ...?"}}











test upvar-8.4 {errors in upvar command} {
    proc p1 {} {upvar 0 b b}
    list [catch p1 msg] $msg
} {1 {can't upvar from variable to itself}}
test upvar-8.5 {errors in upvar command} {
    proc p1 {} {upvar 0 a b; upvar 0 b a}
    list [catch p1 msg] $msg
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    catch {unset upvarArray}
    array set upvarArray {}
    upvar 0 upvarArray(elem) upvarArrayElemAlias(elem)
} -returnCodes 1 -match glob -result *

test upvar-9.1 {Tcl_UpVar2 procedure} testupvar {
    list [catch {testupvar xyz a {} x global} msg] $msg
} {1 {bad level "1"}}
test upvar-9.2 {Tcl_UpVar2 procedure} testupvar {
    catch {unset a}
    catch {unset x}
    set a 44
    list [catch "testupvar #0 a 1 x global" msg] $msg
} {1 {can't access "a(1)": variable isn't array}}
test upvar-9.3 {Tcl_UpVar2 procedure} testupvar {







|







342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    catch {unset upvarArray}
    array set upvarArray {}
    upvar 0 upvarArray(elem) upvarArrayElemAlias(elem)
} -returnCodes 1 -match glob -result *

test upvar-9.1 {Tcl_UpVar2 procedure} testupvar {
    list [catch {testupvar xyz a {} x global} msg] $msg
} {1 {bad level "xyz"}}
test upvar-9.2 {Tcl_UpVar2 procedure} testupvar {
    catch {unset a}
    catch {unset x}
    set a 44
    list [catch "testupvar #0 a 1 x global" msg] $msg
} {1 {can't access "a(1)": variable isn't array}}
test upvar-9.3 {Tcl_UpVar2 procedure} testupvar {
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    rename linenumber {}
} -result 1


#
# Tests for 'namespace upvar'. As the implementation is essentially the same as
# for 'upvar', we only test that the variables are linked correctly. Ie, we
# assume that the behaviour of variables once the link is established has
# already been tested above.
#
#

# Clear out any namespaces called test_ns_*
catch {namespace delete {*}[namespace children :: test_ns_*]}








|







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
    rename linenumber {}
} -result 1


#
# Tests for 'namespace upvar'. As the implementation is essentially the same as
# for 'upvar', we only test that the variables are linked correctly. Ie, we
# assume that the behaviour of variables once the link is established has 
# already been tested above.
#
#

# Clear out any namespaces called test_ns_*
catch {namespace delete {*}[namespace children :: test_ns_*]}

Changes to tests/utf.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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111

1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
# This file contains a collection of tests for tclUtf.c
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]

testConstraint ucs2 [expr {[format %c 0x010000] eq "\uFFFD"}]
testConstraint fullutf [expr {[format %c 0x010000] ne "\uFFFD"}]
testConstraint utf16 [expr {[string length [format %c 0x10000]] == 2}]
testConstraint ucs4 [expr {[testConstraint fullutf]
		&& [string length [format %c 0x10000]] == 1}]

testConstraint Uesc [expr {"\U0041" eq "A"}]
testConstraint pre388 [expr {"\x741" eq "A"}]
testConstraint pairsTo4bytes [expr {[llength [info commands teststringbytes]]
		&& [string length [teststringbytes \uD83D\uDCA9]] == 4}]

testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testfindfirst [llength [info commands testfindfirst]]
testConstraint testfindlast [llength [info commands testfindlast]]
testConstraint testnumutfchars [llength [info commands testnumutfchars]]
testConstraint teststringobj [llength [info commands teststringobj]]
testConstraint testutfnext [llength [info commands testutfnext]]
testConstraint testutfprev [llength [info commands testutfprev]]

testConstraint tip413 [expr {[string trim \x00] eq {}}]

catch {unset x}

test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} testbytestring {

    expr {"\x01" eq [testbytestring \x01]}
} 1
test utf-1.2 {Tcl_UniCharToUtf: 2 byte sequences} testbytestring {
    expr {"\x00" eq [testbytestring \xC0\x80]}
} 1
test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} testbytestring {

    expr {"\xE0" eq [testbytestring \xC3\xA0]}
} 1
test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} testbytestring {

    expr {"\u4E4E" eq [testbytestring \xE4\xB9\x8E]}
} 1
test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring {
    expr {[format %c 0x110000] eq [testbytestring \xEF\xBF\xBD]}
} 1
test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring {
    expr {[format %c -1] eq [testbytestring \xEF\xBF\xBD]}
} 1
test utf-1.7.0 {Tcl_UniCharToUtf: 4 byte sequences} {fullutf testbytestring} {
    expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]}
} 1
test utf-1.7.1 {Tcl_UniCharToUtf: 4 byte sequences} {Uesc ucs2 testbytestring} {
    expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]}
} 0
test utf-1.8 {Tcl_UniCharToUtf: 3 byte sequence, high surrogate} testbytestring {
    expr {"\uD842" eq [testbytestring \xED\xA1\x82]}
} 1
test utf-1.9 {Tcl_UniCharToUtf: 3 byte sequence, low surrogate} testbytestring {
    expr {"\uDC42" eq [testbytestring \xED\xB1\x82]}
} 1
test utf-1.10 {Tcl_UniCharToUtf: 3 byte sequence, high surrogate} testbytestring {
    expr {[format %c 0xD842] eq [testbytestring \xED\xA1\x82]}
} 1
test utf-1.11 {Tcl_UniCharToUtf: 3 byte sequence, low surrogate} testbytestring {
    expr {[format %c 0xDC42] eq [testbytestring \xED\xB1\x82]}
} 1
test utf-1.12 {Tcl_UniCharToUtf: 4 byte sequence, high/low surrogate} {pairsTo4bytes testbytestring} {
    expr {"\uD842\uDC42" eq [testbytestring \xF0\xA0\xA1\x82]}
} 1
test utf-1.13.0 {Tcl_UniCharToUtf: Invalid surrogate} {Uesc ucs2} {
    expr {"\UD842" eq "\uD842"}
} 1
test utf-1.13.1 {Tcl_UniCharToUtf: Invalid surrogate} {fullutf testbytestring} {
    expr {"\UD842" eq [testbytestring \xEF\xBF\xBD]}
} 1

test utf-2.1 {Tcl_UtfToUniChar: low ascii} {
    string length "abc"
} 3
test utf-2.2 {Tcl_UtfToUniChar: naked trail bytes} testbytestring {
    string length [testbytestring \x82\x83\x84]
} 3
test utf-2.3 {Tcl_UtfToUniChar: lead (2-byte) followed by non-trail} testbytestring {
    string length [testbytestring \xC2]
} 1
test utf-2.4 {Tcl_UtfToUniChar: lead (2-byte) followed by trail} {
    string length \xA2
} 1
test utf-2.5 {Tcl_UtfToUniChar: lead (3-byte) followed by non-trail} testbytestring {
    string length [testbytestring \xE2]
} 1
test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} testbytestring {
    string length [testbytestring \xE2\xA2]
} 2
test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} testbytestring {
    string length [testbytestring \xE4\xB9\x8E]
} 1
test utf-2.8.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {ucs2 testbytestring} {
    string length [testbytestring \xF0\x90\x80\x80]
} 4
test utf-2.8.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} utf16 {
    string length \U010000
} 2
test utf-2.8.2 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} ucs4 {
    string length \U010000
} 1
test utf-2.9.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {ucs2 testbytestring} {
    string length [testbytestring \xF4\x8F\xBF\xBF]
} 4
test utf-2.9.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} utf16 {
    string length \U10FFFF
} 2
test utf-2.9.2 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} ucs4 {
    string length \U10FFFF
} 1
test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} testbytestring {
    string length [testbytestring \xF0\x8F\xBF\xBF]
} 4
test utf-2.11 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, overflow} testbytestring {
    # Would decode to U+110000 but that is outside the Unicode range.
    string length [testbytestring \xF4\x90\x80\x80]
} 4
test utf-2.12 {Tcl_UtfToUniChar: longer UTF sequences not supported} testbytestring {
    string length [testbytestring \xF8\xA2\xA2\xA2\xA2]
} 5

test utf-3.1 {Tcl_UtfCharComplete} {
} {}


test utf-4.1 {Tcl_NumUtfChars: zero length} testnumutfchars {
    testnumutfchars ""
} 0
test utf-4.2 {Tcl_NumUtfChars: length 1} testnumutfchars {
    testnumutfchars \xA2
} 1
test utf-4.3 {Tcl_NumUtfChars: long string} {testnumutfchars testbytestring} {
    testnumutfchars abc\xA2[testbytestring \xE4\xB9\x8E\xA2\x4E]
} 7
test utf-4.4 {Tcl_NumUtfChars: #x00} testnumutfchars {
    testnumutfchars \x00
} 1
test utf-4.5 {Tcl_NumUtfChars: zero length, calc len} testnumutfchars {
    testnumutfchars "" 0
} 0
test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} {testnumutfchars testbytestring} {
    testnumutfchars \xA2 end
} 1
test utf-4.7 {Tcl_NumUtfChars: long string, calc len} {testnumutfchars testbytestring} {
    testnumutfchars abc\xA2[testbytestring \xE4\xB9\x8E\xA2\x4E] end
} 7
test utf-4.8 {Tcl_NumUtfChars: #x00, calc len} testnumutfchars {
    testnumutfchars \x00 end
} 1
# Bug [2738427]: Tcl_NumUtfChars(...) no overflow check
test utf-4.9 {Tcl_NumUtfChars: #u20AC, calc len, incomplete} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xE2\x82\xAC] end-1
} 2
test utf-4.10 {Tcl_NumUtfChars: #x00, calc len, overcomplete} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \x00] end+1
} 2
test utf-4.11 {Tcl_NumUtfChars: 3 bytes of 4-byte UTF-8 characater} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end-1
} 3
test utf-4.12.0 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring ucs2} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end
} 4
test utf-4.12.1 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring ucs4} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end
} 1
test utf-4.13 {Tcl_NumUtfChars: end of string} {testnumutfchars testbytestring} {
    testnumutfchars foobar[testbytestring \xF2\xC2\xA0] end
} 8
test utf-4.14 {Tcl_NumUtfChars: 3 bytes of 4-byte UTF-8 characater} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xF4\x90\x80\x80] end-1
} 3

test utf-5.1 {Tcl_UtfFindFirst} {testfindfirst testbytestring} {
    testfindfirst [testbytestring abcbc] 98
} bcbc
test utf-5.2 {Tcl_UtfFindLast} {testfindlast testbytestring} {
    testfindlast [testbytestring abcbc] 98
} bc

test utf-6.1 {Tcl_UtfNext} {testutfnext testbytestring} {
    # This takes the pointer one past the terminating NUL.
    # This is really an invalid call.
    testutfnext [testbytestring \x00]
} 1
test utf-6.2 {Tcl_UtfNext} testutfnext {
    testutfnext A
} 1
test utf-6.3 {Tcl_UtfNext} testutfnext {
    testutfnext AA
} 1
test utf-6.4 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring A\xA0]
} 1
test utf-6.5 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xD0]
} 1
test utf-6.6 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xE8]
} 1
test utf-6.7 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xF2]
} 1
test utf-6.8 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xF8]
} 1
test utf-6.9 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0]
} 1
test utf-6.10 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0]G
} 1
test utf-6.11.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\x00]
} 1
test utf-6.11.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\x00]
} 2
test utf-6.12 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xD0]
} 1
test utf-6.13 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xE8]
} 1
test utf-6.14 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xF2]
} 1
test utf-6.15 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xF8]
} 1
test utf-6.16 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\x00]
} 1
test utf-6.17 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0]G
} 1
test utf-6.18 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0]
} 2
test utf-6.19 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xD0]
} 1
test utf-6.20 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xE8]
} 1
test utf-6.21 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xF2]
} 1
test utf-6.22 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xF8]
} 1
test utf-6.23 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\x00]
} 1
test utf-6.24 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8]G
} 1
test utf-6.25 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\x00]
} 1
test utf-6.26 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xD0]
} 1
test utf-6.27 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xE8]
} 1
test utf-6.28 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xF2]
} 1
test utf-6.29 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xF8]
} 1
test utf-6.30.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2]
} 1
test utf-6.30.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\x00]
} 1
test utf-6.31 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2]G
} 1
test utf-6.32.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0]
} 1
test utf-6.32.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\x00]
} 1
test utf-6.33 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xD0]
} 1
test utf-6.34 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xE8]
} 1
test utf-6.35 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xF2]
} 1
test utf-6.36 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xF8]
} 1
test utf-6.37 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8]
} 1
test utf-6.38 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8]G
} 1
test utf-6.39 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8\xA0]
} 1
test utf-6.40 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8\xD0]
} 1
test utf-6.41 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8\xE8]
} 1
test utf-6.42 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8\xF2]
} 1
test utf-6.43 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8\xF8]
} 1
test utf-6.44 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0]G
} 2
test utf-6.45 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xA0]
} 2
test utf-6.46 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xD0]
} 2
test utf-6.47 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xE8]
} 2
test utf-6.48 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xF2]
} 2
test utf-6.49 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xF8]
} 2
test utf-6.50 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0]G
} 1
test utf-6.51 {Tcl_UtfNext} testutfnext {
    testutfnext \u8820
} 3
test utf-6.52 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xD0]
} 1
test utf-6.53 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xE8]
} 1
test utf-6.54 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xF2]
} 1
test utf-6.55 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xF8]
} 1
test utf-6.56 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0]G
} 1
test utf-6.57 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\x00]
} 1
test utf-6.58 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xD0]
} 1
test utf-6.59 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xE8]
} 1
test utf-6.60 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xF2]
} 1
test utf-6.61 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xF8]
} 1
test utf-6.62 {Tcl_UtfNext} testutfnext {
    testutfnext \u8820G
} 3
test utf-6.63 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xA0\xA0]
} 3
test utf-6.64 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xD0]
} 3
test utf-6.65 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xE8]
} 3
test utf-6.66 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xF2]
} 3
test utf-6.67 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xF8]
} 3
test utf-6.68 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0]G
} 1
test utf-6.69.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]
} 1
test utf-6.69.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]
} 4
test utf-6.70 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xD0]
} 1
test utf-6.71 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xE8]
} 1
test utf-6.72 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xF2]
} 1
test utf-6.73 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xF8]
} 1
test utf-6.74.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G
} 1
test utf-6.74.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G
} 4
test utf-6.75.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0]
} 1
test utf-6.75.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0]
} 4
test utf-6.76.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0]
} 1
test utf-6.76.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0]
} 4
test utf-6.77.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8]
} 1
test utf-6.77.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8]
} 4
test utf-6.78.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2]
} 1
test utf-6.78.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2]
} 4
test utf-6.79.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8]
} 1
test utf-6.79.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8]
} 4
test utf-6.80 {Tcl_UtfNext - overlong sequences} testutfnext {
    testutfnext \x00
} 2
test utf-6.81 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xC0\x81]
} 1
test utf-6.82 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xC1\x80]
} 1
test utf-6.83 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xC2\x80]
} 2
test utf-6.84 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE0\x80\x80]
} 1
test utf-6.85 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE0\xA0\x80]
} 3
test utf-6.86 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF0\x80\x80\x80]
} 1
test utf-6.87.0 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF0\x90\x80\x80]
} 1
test utf-6.87.1 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF0\x90\x80\x80]
} 4
test utf-6.88.0 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\x00]
} 1
test utf-6.88.1 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\x00]
} 2
test utf-6.89.0 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \x80\x80\x00]
} 1
test utf-6.89.1 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \x80\x80\x00]
} 2
test utf-6.90.0 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF4\x8F\xBF\xBF]
} 1
test utf-6.90.1 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF4\x8F\xBF\xBF]
} 4
test utf-6.91 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF4\x90\x80\x80]
} 1
test utf-6.92.0 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0]
} 1
test utf-6.92.1 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0]
} 3
test utf-6.93.0 {Tcl_UtfNext, pointing to 2th byte of 4-byte invalid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \x80\x80\x80]
} 1
test utf-6.93.1 {Tcl_UtfNext, pointing to 2th byte of 4-byte invalid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \x80\x80\x80]
} 3
test utf-6.94.0 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0]
} 1
test utf-6.94.1 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0]
} 3
test utf-6.95.0 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \x80\x80\x80\x80]
} 1
test utf-6.95.1 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \x80\x80\x80\x80]
} 3
test utf-6.96 {Tcl_UtfNext, read limits} testutfnext {
    testutfnext G 0
} 0
test utf-6.97 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0] 0
} 0
test utf-6.98 {Tcl_UtfNext, read limits} testutfnext {
    testutfnext AG 1
} 1
test utf-6.99 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xA0] 1
} 1
test utf-6.100 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0]G 1
} 0
test utf-6.101 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0]G 2
} 2
test utf-6.102 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xA0] 1
} 0
test utf-6.103 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xA0] 2
} 2
test utf-6.104 {Tcl_UtfNext, read limits} testutfnext {
    testutfnext \u8820G 1
} 0
test utf-6.105 {Tcl_UtfNext, read limits} testutfnext {
    testutfnext \u8820G 2
} 0
test utf-6.106 {Tcl_UtfNext, read limits} testutfnext {
    testutfnext \u8820G 3
} 3
test utf-6.107 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xA0] 1
} 0
test utf-6.108 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xA0] 2
} 0
test utf-6.109 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xA0] 3
} 3
test utf-6.110 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 1
} 1
test utf-6.111 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 2
} 1
test utf-6.112.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 3
} 1
test utf-6.112.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 3
} 0
test utf-6.113.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 4
} 1
test utf-6.113.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G 4
} 4
test utf-6.114 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 1
} 1
test utf-6.115 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 2
} 1
test utf-6.116.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 3
} 1
test utf-6.116.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 3
} 0
test utf-6.117.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 4
} 1
test utf-6.117.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] 4
} 4
test utf-6.118 {Tcl_UtfNext, read limits} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0]G 0
} 0
test utf-6.119 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0]G 1
} 1
test utf-6.120 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0] 1
} 1
test utf-6.121 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0]G 2
} 1
test utf-6.122 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0] 2
} 1
test utf-6.123.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0]G 3
} 1
test utf-6.123.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0]G 3
} 3
test utf-6.124.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0] 3
} 1
test utf-6.124.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0] 3
} 3
test utf-6.125.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0]G 4
} 1
test utf-6.125.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0]G 4
} 3
test utf-6.126.0 {Tcl_UtfNext, read limits} {testutfnext testbytestring ucs2} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0\xA0] 4
} 1
test utf-6.126.1 {Tcl_UtfNext, read limits} {testutfnext testbytestring fullutf} {
    testutfnext [testbytestring \xA0\xA0\xA0\xA0\xA0] 4
} 3

test utf-7.1 {Tcl_UtfPrev} testutfprev {
    testutfprev {}
} 0
test utf-7.2 {Tcl_UtfPrev} testutfprev {
    testutfprev A
} 0
test utf-7.3 {Tcl_UtfPrev} testutfprev {
    testutfprev AA
} 1
test utf-7.4 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8]
} 1
test utf-7.4.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0] 2
} 1
test utf-7.4.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xF8\xA0\xA0] 2
} 1
test utf-7.5 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2]
} 1
test utf-7.5.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 2
} 1
test utf-7.5.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xF8\xA0\xA0] 2
} 1
test utf-7.6 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8]
} 1
test utf-7.6.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 2
} 1
test utf-7.6.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xF8\xA0\xA0] 2
} 1
test utf-7.7 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0]
} 1
test utf-7.7.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 2
} 1
test utf-7.7.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xF8\xA0\xA0] 2
} 1
test utf-7.8 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0]
} 1
test utf-7.8.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 2
} 1
test utf-7.8.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xF8\xA0\xA0] 2
} 1
test utf-7.9 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0]
} 2
test utf-7.9.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0] 3
} 2
test utf-7.9.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xF8\xA0] 3
} 2
test utf-7.10.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0]
} 2
test utf-7.10.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0]
} 1
test utf-7.10.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 3
} 2
test utf-7.10.3 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 3
} 1
test utf-7.10.4 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xF8\xA0] 3
} 2
test utf-7.10.5 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xF8\xA0] 3
} 1
test utf-7.11 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0]
} 1
test utf-7.11.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 3
} 1
test utf-7.11.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xF8\xA0] 3
} 1
test utf-7.11.3 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xF8] 3
} 1
test utf-7.12 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0]
} 1
test utf-7.12.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 3
} 1
test utf-7.12.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xF8\xA0] 3
} 1
test utf-7.13 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0]
} 2
test utf-7.13.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 3
} 2
test utf-7.13.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xF8\xA0] 3
} 2
test utf-7.14 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0]
} 3
test utf-7.14.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0] 4
} 3
test utf-7.14.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xF8] 4
} 3
test utf-7.15.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xA0]
} 3
test utf-7.15.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0]
} 1
test utf-7.15.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 4
} 3
test utf-7.15.3 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 4
} 1
test utf-7.15.4 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4
} 3
test utf-7.15.5 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4
} 1
test utf-7.16 {Tcl_UtfPrev} testutfprev {
    testutfprev A\u8820
} 1
test utf-7.16.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 4
} 1
test utf-7.16.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xF8] 4
} 1
test utf-7.17 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0]
} 3
test utf-7.17.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 4
} 3
test utf-7.17.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xF8] 4
} 3
test utf-7.18.0 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0]
} 3
test utf-7.18.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 4
} 3
test utf-7.18.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xF8] 4
} 3
test utf-7.19 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xF8\xA0\xA0\xA0]
} 4
test utf-7.20.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev [testbytestring A\xF2\xA0\xA0\xA0]
} 4
test utf-7.20.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev [testbytestring A\xF2\xA0\xA0\xA0]
} 1
test utf-7.21 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0]
} 4
test utf-7.22 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0]
} 4
test utf-7.23 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0]
} 4
test utf-7.24 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC0\x81]
} 2
test utf-7.25 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC0\x81] 2
} 1
test utf-7.26 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\x80\x80]
} 3
test utf-7.27 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\x80]
} 2
test utf-7.27.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\x80\x80] 3
} 2
test utf-7.28 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0]
} 1
test utf-7.28.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\x80\x80] 2
} 1
test utf-7.29 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80]
} 4
test utf-7.30 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80] 4
} 3
test utf-7.31 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80] 3
} 2
test utf-7.32 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80] 2
} 1
test utf-7.33 {Tcl_UtfPrev -- overlong sequence}  testutfprev {
    testutfprev A\x00
} 1
test utf-7.34 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC1\x80]
} 2
test utf-7.35 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC2\x80]
} 1
test utf-7.36 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\xA0\x80]
} 1
test utf-7.37 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\xA0\x80] 3
} 1
test utf-7.38 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\xA0\x80] 2
} 1
test utf-7.39.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF0\x90\x80\x80]
} 4
test utf-7.39.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF0\x90\x80\x80]
} 1
test utf-7.40.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 4
} 3
test utf-7.40.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 4
} 1
test utf-7.41.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 3
} 2
test utf-7.41.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 3
} 1
test utf-7.42 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 2
} 1
test utf-7.43 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0]
} 0
test utf-7.44 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0]
} 1
test utf-7.45 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0\xA0]
} 2
test utf-7.46 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0\xA0\xA0]
} 3
test utf-7.47 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} {testutfprev testbytestring} {
    testutfprev [testbytestring \xE8\xA0]
} 0
test utf-7.47.1 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} testutfprev {
    testutfprev \u8820 2
} 0
test utf-7.47.2 {Tcl_UtfPrev, pointing to 3th byte of 3-byte invalid sequence} {testutfprev testbytestring} {
    testutfprev [testbytestring \xE8\xA0\x00] 2
} 0
test utf-7.48.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF]
} 4
test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF]
} 1
test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4
} 3
test utf-7.48.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4
} 1
test utf-7.48.4 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3
} 2
test utf-7.48.5 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3
} 1
test utf-7.48.6 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 2
} 1
test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80]
} 4
test utf-7.49.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 4
} 3
test utf-7.49.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 3
} 2
test utf-7.49.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 2
} 1

test utf-8.1 {Tcl_UniCharAtIndex: index = 0} {
    string index abcd 0
} a
test utf-8.2 {Tcl_UniCharAtIndex: index = 0} {
    string index \u4E4E\u25A 0
} \u4E4E
test utf-8.3 {Tcl_UniCharAtIndex: index > 0} {
    string index abcd 2
} c
test utf-8.4 {Tcl_UniCharAtIndex: index > 0} {
    string index \u4E4E\u25A\xFF\u543 2
} \xFF
test utf-8.5.0 {Tcl_UniCharAtIndex: high surrogate} ucs2 {
    string index \uD842 0
} \uD842
test utf-8.5.1 {Tcl_UniCharAtIndex: high surrogate} ucs4 {
    string index \uD842 0
} \uD842
test utf-8.5.2 {Tcl_UniCharAtIndex: high surrogate} utf16 {
    string index \uD842 0
} \uD842
test utf-8.6 {Tcl_UniCharAtIndex: low surrogate} {
    string index \uDC42 0
} \uDC42
test utf-8.7.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 0
} \uD83D
test utf-8.7.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 0
} \U1F600
test utf-8.7.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 0
} \U1F600
test utf-8.8.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 1
} \uDE00
test utf-8.8.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 1
} G
test utf-8.8.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 1
} {}
test utf-8.9.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 2
} G
test utf-8.9.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 2
} {}
test utf-8.9.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 2
} G
test utf-8.10.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 0
} \uFFFD
test utf-8.10.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 0
} \U1F600
test utf-8.10.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 0
} \U1F600
test utf-8.11.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 1
} G
test utf-8.11.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 1
} G
test utf-8.11.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 1
} {}
test utf-8.12.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 2
} {}
test utf-8.12.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \U1F600G 2
} {}
test utf-8.12.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \U1F600G 2
} G

test utf-9.1 {Tcl_UtfAtIndex: index = 0} {
    string range abcd 0 2
} abc
test utf-9.2 {Tcl_UtfAtIndex: index > 0} {
    string range \u4E4E\u25A\xFF\u543klmnop 1 5
} \u25A\xFF\u543kl
test utf-9.3.0 {Tcl_UtfAtIndex: index = 0, Emoji} ucs2 {
    string range \uD83D\uDE00G 0 0
} \uD83D
test utf-9.3.1 {Tcl_UtfAtIndex: index = 0, Emoji} ucs4 {
    string range \U1F600G 0 0
} \U1F600
test utf-9.3.2 {Tcl_UtfAtIndex: index = 0, Emoji} utf16 {
    string range \U1F600G 0 0
} \U1F600
test utf-9.4.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 {
    string range \uD83D\uDE00G 1 1
} \uDE00
test utf-9.4.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \U1F600G 1 1
} G
test utf-9.4.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \U1F600G 1 1
} {}
test utf-9.5.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 {
    string range \uD83D\uDE00G 2 2
} G
test utf-9.5.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \U1F600G 2 2
} {}
test utf-9.5.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \U1F600G 2 2
} G
test utf-9.6.0 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc ucs2} {
    string range \U1F600G 0 0
} \uFFFD
test utf-9.6.1 {Tcl_UtfAtIndex: index = 0, Emoji} ucs4 {
    string range \U1F600G 0 0
} \U1F600
test utf-9.6.2 {Tcl_UtfAtIndex: index = 0, Emoji} utf16 {
    string range \U1F600G 0 0
} \U1F600
test utf-9.7.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} {
    string range \U1F600G 1 1
} G
test utf-9.7.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \U1F600G 1 1
} G
test utf-9.7.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \U1F600G 1 1
} {}
test utf-9.8.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} {
    string range \U1F600G 2 2
} {}
test utf-9.8.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \U1F600G 2 2
} {}
test utf-9.8.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \U1F600G 2 2
} G

test utf-10.1 {Tcl_UtfBackslash: dst == NULL} {
    set x \n
} {
}
test utf-10.2 {Tcl_UtfBackslash: \u subst} testbytestring {

    expr {"\uA2" eq [testbytestring \xC2\xA2]}
} 1
test utf-10.3 {Tcl_UtfBackslash: longer \u subst} testbytestring {

    expr {"\u4E21" eq [testbytestring \xE4\xB8\xA1]}
} 1
test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} testbytestring {

    expr {"\u4E2k" eq "[testbytestring \xD3\xA2]k"}
} 1
test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} testbytestring {
    expr {"\u4E216" eq "[testbytestring \xE4\xB8\xA1]6"}
} 1
test utf-10.6 {Tcl_UtfBackslash: stops after 5 hex chars} {fullutf testbytestring} {
    expr {"\U1E2165" eq "[testbytestring \xF0\x9E\x88\x96]5"}
} 1
test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} {fullutf testbytestring} {
    expr {"\U10E2165" eq "[testbytestring \xF4\x8E\x88\x96]5"}
} 1

proc bsCheck {char num {constraints {}}} {
    global errNum
    test utf-10.$errNum {backslash substitution} $constraints {
	scan $char %c value
	set value
    } $num
    incr errNum
}
set errNum 8
bsCheck \b	8
bsCheck \e	101
bsCheck \f	12
bsCheck \n	10
bsCheck \r	13
bsCheck \t	9
bsCheck \v	11





|




|
|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
>
|
<
|
|
|
|
>
|
<
|
>
|
<
|
|
|
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|




>


|

|
|
|
|
|
|
|
|

|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|

|
|


|

<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|
>
|
<
|
>
|
<
|
>
|
<
|
<
|
<
<
<
<
<
<
|
|

|





|







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






































120
121
122
123
124
125
126
127

128
129
130

131
132
133

134

135






136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# This file contains a collection of tests for tclUtf.c
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

























catch {unset x}

test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} {
    set x \x01
} [bytestring "\x01"]

test utf-1.2 {Tcl_UniCharToUtf: 2 byte sequences} {
    set x "\x00"
} [bytestring "\xc0\x80"]
test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} {
    set x "\xe0"
} [bytestring "\xc3\xa0"]

test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} {
    set x "\u4e4e"
} [bytestring "\xe4\xb9\x8e"]

test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} {
    format %c 0x110000
} [bytestring "\xef\xbf\xbd"]
test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} {
    format %c -1








} [bytestring "\xef\xbf\xbd"]




















test utf-2.1 {Tcl_UtfToUniChar: low ascii} {
    string length "abc"
} {3}
test utf-2.2 {Tcl_UtfToUniChar: naked trail bytes} {
    string length [bytestring "\x82\x83\x84"]
} {3}
test utf-2.3 {Tcl_UtfToUniChar: lead (2-byte) followed by non-trail} {
    string length [bytestring "\xC2"]
} {1}
test utf-2.4 {Tcl_UtfToUniChar: lead (2-byte) followed by trail} {
    string length [bytestring "\xC2\xa2"]
} {1}
test utf-2.5 {Tcl_UtfToUniChar: lead (3-byte) followed by non-trail} {
    string length [bytestring "\xE2"]
} {1}
test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} {
    string length [bytestring "\xE2\xA2"]
} {2}
test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} {






    string length [bytestring "\xE4\xb9\x8e"]
} {1}



















test utf-2.8 {Tcl_UtfToUniChar: longer UTF sequences not supported} {
    string length [bytestring "\xF4\xA2\xA2\xA2"]
} {4}

test utf-3.1 {Tcl_UtfCharComplete} {
} {}

testConstraint testnumutfchars [llength [info commands testnumutfchars]]
test utf-4.1 {Tcl_NumUtfChars: zero length} testnumutfchars {
    testnumutfchars ""
} {0}
test utf-4.2 {Tcl_NumUtfChars: length 1} testnumutfchars {
    testnumutfchars [bytestring "\xC2\xA2"]
} {1}
test utf-4.3 {Tcl_NumUtfChars: long string} testnumutfchars {
    testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"]
} {7}
test utf-4.4 {Tcl_NumUtfChars: #u0000} testnumutfchars {
    testnumutfchars [bytestring "\xC0\x80"]
} {1}
test utf-4.5 {Tcl_NumUtfChars: zero length, calc len} testnumutfchars {
    testnumutfchars "" 1
} {0}
test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} testnumutfchars {
    testnumutfchars [bytestring "\xC2\xA2"] 1
} {1}





































































































































































































test utf-4.7 {Tcl_NumUtfChars: long string, calc len} testnumutfchars {















    testnumutfchars [bytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 1
} {7}















test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} testnumutfchars {






















































































































































    testnumutfchars [bytestring "\xC0\x80"] 1
} {1}
















































































































test utf-5.1 {Tcl_UtfFindFirsts} {

} {}







































































































































test utf-6.1 {Tcl_UtfNext} {

} {}









test utf-7.1 {Tcl_UtfPrev} {

} {}





























































































































































test utf-8.1 {Tcl_UniCharAtIndex: index = 0} {
    string index abcd 0
} {a}
test utf-8.2 {Tcl_UniCharAtIndex: index = 0} {
    string index \u4e4e\u25a 0
} "\u4e4e"
test utf-8.3 {Tcl_UniCharAtIndex: index > 0} {
    string index abcd 2
} {c}
test utf-8.4 {Tcl_UniCharAtIndex: index > 0} {



    string index \u4e4e\u25a\xff\u543 2
























} "\uff"








































test utf-9.1 {Tcl_UtfAtIndex: index = 0} {
    string range abcd 0 2
} {abc}
test utf-9.2 {Tcl_UtfAtIndex: index > 0} {






    string range \u4e4e\u25a\xff\u543klmnop 1 5









} "\u25a\xff\u543kl"








































test utf-10.1 {Tcl_UtfBackslash: dst == NULL} {
    set x \n
} {
}
test utf-10.2 {Tcl_UtfBackslash: \u subst} {
    set x \ua2
} [bytestring "\xc2\xa2"]

test utf-10.3 {Tcl_UtfBackslash: longer \u subst} {
    set x \u4e21
} [bytestring "\xe4\xb8\xa1"]

test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} {
    set x \u4e2k
} "[bytestring \xd3\xa2]k"

test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} {

    set x \u4e216






} "[bytestring \xe4\xb8\xa1]6"
proc bsCheck {char num} {
    global errNum
    test utf-10.$errNum {backslash substitution} {
	scan $char %c value
	set value
    } $num
    incr errNum
}
set errNum 6
bsCheck \b	8
bsCheck \e	101
bsCheck \f	12
bsCheck \n	10
bsCheck \r	13
bsCheck \t	9
bsCheck \v	11
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425



1426



1427
1428
1429

1430
1431
1432
1433
1434
1435


1436

1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450

1451

1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465


1466


1467

1468
1469

1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
bsCheck \14	12
bsCheck \141	97
bsCheck b\0	98
bsCheck \x	120
bsCheck \xa	10
bsCheck \xA	10
bsCheck \x41	65
bsCheck \x541	65	pre388	;# == \x41
bsCheck \x541	84	!pre388	;# == \x54 1
bsCheck \u	117
bsCheck \uk	117
bsCheck \u41	65
bsCheck \ua	10
bsCheck \uA	10
bsCheck \340	224
bsCheck \uA1	161
bsCheck \u4E21	20001
bsCheck \741    225	pre388	;# == \341
bsCheck \741    60	!pre388	;# == \74 1
bsCheck \U      85
bsCheck \Uk     85
bsCheck \U41    65			Uesc
bsCheck \Ua     10			Uesc
bsCheck \UA     10			Uesc
bsCheck \UA1    161			Uesc
bsCheck \U4E21  20001			Uesc
bsCheck \U004E21        20001		Uesc
bsCheck \U00004E21      20001		Uesc
bsCheck \U0000004E21    78		Uesc
bsCheck \U00110000      69632		fullutf
bsCheck \U01100000      69632		fullutf
bsCheck \U11000000      69632		fullutf
bsCheck \U0010FFFF      1114111		fullutf
bsCheck \U010FFFF0      1114111		fullutf
bsCheck \U10FFFF00      1114111		fullutf
bsCheck \UFFFFFFFF      1048575		fullutf

test utf-11.1 {Tcl_UtfToUpper} {
    string toupper {}
} {}
test utf-11.2 {Tcl_UtfToUpper} {
    string toupper abc
} ABC
test utf-11.3 {Tcl_UtfToUpper} {
    string toupper \xE3gh
} \xC3GH
test utf-11.4 {Tcl_UtfToUpper} {
    string toupper \u01E3gh
} \u01E2GH
test utf-11.5 {Tcl_UtfToUpper Georgian (new in Unicode 11)} {
    string toupper \u10D0\u1C90
} \u1C90\u1C90
test utf-11.6 {Tcl_UtfToUpper beyond U+FFFF} fullutf {
    string toupper \U10428
} \U10400
test utf-11.7 {Tcl_UtfToUpper beyond U+FFFF} fullutf {
    string toupper \uD801\uDC28
} \uD801\uDC00
test utf-11.8 {Tcl_UtfToUpper low/high surrogate)} {
    string toupper \uDC24\uD824
} \uDC24\uD824

test utf-12.1 {Tcl_UtfToLower} {
    string tolower {}
} {}
test utf-12.2 {Tcl_UtfToLower} {
    string tolower ABC
} abc
test utf-12.3 {Tcl_UtfToLower} {
    string tolower \xC3GH
} \xE3gh
test utf-12.4 {Tcl_UtfToLower} {
    string tolower \u01E2GH
} \u01E3gh
test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} {
    string tolower \u10D0\u1C90
} \u10D0\u10D0
test utf-12.6 {Tcl_UtfToLower low/high surrogate)} {
    string tolower \uDC24\uD824
} \uDC24\uD824
test utf-12.7 {Tcl_UtfToLower beyond U+FFFF} fullutf {
    string tolower \U10400
} \U10428
test utf-12.8 {Tcl_UtfToLower beyond U+FFFF} fullutf {
    string tolower \uD801\uDC00
} \uD801\uDC28

test utf-13.1 {Tcl_UtfToTitle} {
    string totitle {}
} {}
test utf-13.2 {Tcl_UtfToTitle} {
    string totitle abc
} Abc
test utf-13.3 {Tcl_UtfToTitle} {
    string totitle \xE3GH
} \xC3gh
test utf-13.4 {Tcl_UtfToTitle} {
    string totitle \u01F3AB
} \u01F2ab
test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u10D0\u1C90
} \u10D0\u1C90
test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u1C90\u10D0
} \u1C90\u10D0
test utf-13.7 {Tcl_UtfToTitle low/high surrogate)} {
    string totitle \uDC24\uD824
} \uDC24\uD824
test utf-13.8 {Tcl_UtfToTitle beyond U+FFFF} fullutf {
    string totitle \U10428\U10400
} \U10400\U10428
test utf-13.9 {Tcl_UtfToTitle beyond U+FFFF} fullutf {
    string totitle \uD801\uDC28\uD801\uDC00
} \uD801\uDC00\uD801\uDC28

test utf-14.1 {Tcl_UtfNcasecmp} {
    string compare -nocase a b
} -1
test utf-14.2 {Tcl_UtfNcasecmp} {
    string compare -nocase b a
} 1
test utf-14.3 {Tcl_UtfNcasecmp} {
    string compare -nocase B a
} 1
test utf-14.4 {Tcl_UtfNcasecmp} {
    string compare -nocase aBcB abca
} 1

test utf-15.1 {Tcl_UniCharToUpper, negative delta} {
    string toupper aA
} AA
test utf-15.2 {Tcl_UniCharToUpper, positive delta} {
    string toupper \u0178\xFF
} \u0178\u0178
test utf-15.3 {Tcl_UniCharToUpper, no delta} {
    string toupper !
} !

test utf-16.1 {Tcl_UniCharToLower, negative delta} {
    string tolower aA
} aa
test utf-16.2 {Tcl_UniCharToLower, positive delta} {
    string tolower \u0178\xFF\uA78D\u01C5
} \xFF\xFF\u0265\u01C6

test utf-17.1 {Tcl_UniCharToLower, no delta} {
    string tolower !
} !

test utf-18.1 {Tcl_UniCharToTitle, add one for title} {
    string totitle \u01C4
} \u01C5
test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} {
    string totitle \u01C6
} \u01C5
test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} {
    string totitle \u017F
} \x53
test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} {
    string totitle \xFF
} \u0178
test utf-18.5 {Tcl_UniCharToTitle, no delta} {
    string totitle !
} !

test utf-19.1 {TclUniCharLen} -body {
    list [regexp \\d abc456def foo] $foo
} -cleanup {
    unset -nocomplain foo
} -result {1 4}

test utf-20.1 {TclUniCharNcmp} ucs4 {
    string compare [string range [format %c 0xFFFF] 0 0] [string range [format %c 0x10000] 0 0]
} -1
test utf-20.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} {
    set one [format %c 0xFFFF]
    set two [format %c 0x10000]
    set first [string compare $one $two]
    string range $one 0 0
    string range $two 0 0
    set second [string compare $one $two]
    expr {($first == $second) ? "agree" : "disagree"}
} agree

test utf-21.1 {TclUniCharIsAlnum} {
    # this returns 1 with Unicode 7 compliance
    string is alnum \u1040\u021F\u0220
} 1
test utf-21.2 {unicode alnum char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:alnum:]]+$} \u1040\u021F\u0220] [regexp {^\w+$} \u1040\u021F\u0220_\u203F\u2040\u2054\uFE33\uFE34\uFE4D\uFE4E\uFE4F\uFF3F]
} {1 1}
test utf-21.3 {unicode print char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:print:]]+$} \uFBC1
} 1
test utf-21.4 {TclUniCharIsGraph} {
    # [Bug 3464428]
    string is graph \u0120
} 1
test utf-21.5 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {^[[:graph:]]+$} \u0120
} 1
test utf-21.6 {TclUniCharIsGraph} {
    # [Bug 3464428]
    string is graph \xA0
} 0
test utf-21.7 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:graph:]]} \x20\xA0\u2028\u2029
} 0
test utf-21.8 {TclUniCharIsPrint} {
    # [Bug 3464428]
    string is print \x09
} 0
test utf-21.9 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \x09
} 0
test utf-21.10 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \x09
} 0
test utf-21.11 {TclUniCharIsControl} {
    # [Bug 3464428]
    string is control \x00\x1F\xAD\u0605\u061C\u180E\u2066\uFEFF
} 1
test utf-21.12 {unicode control char in regc_locale.c} {
    # [Bug 3464428], [Bug a876646efe]
    regexp {^[[:cntrl:]]*$} \x00\x1F\xAD\u0605\u061C\u180E\u2066\uFEFF
} 1

test utf-22.1 {TclUniCharIsWordChar} {
    string wordend "xyz123_bar fg" 0
} 10
test utf-22.2 {TclUniCharIsWordChar} {
    string wordend "x\u5080z123_bar\u203C fg" 0
} 10

test utf-23.1 {TclUniCharIsAlpha} {
    # this returns 1 with Unicode 7 compliance
    string is alpha \u021F\u0220\u037F\u052F
} 1
test utf-23.2 {unicode alpha char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:alpha:]]+$} \u021F\u0220\u037F\u052F
} 1

test utf-24.1 {TclUniCharIsDigit} {
    # this returns 1 with Unicode 7 compliance
    string is digit \u1040\uABF0
} 1
test utf-24.2 {unicode digit char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:digit:]]+$} \u1040\uABF0] [regexp {^\d+$} \u1040\uABF0]
} {1 1}

test utf-24.3 {TclUniCharIsSpace} {
    # this returns 1 with Unicode 7 compliance
    string is space \u1680\u180E\u202F
} 1
test utf-24.4 {unicode space char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:space:]]+$} \u1680\u180E\u202F] [regexp {^\s+$} \u1680\u180E\u202F]
} {1 1}
test utf-24.5 {TclUniCharIsSpace} tip413 {
    # this returns 1 with Unicode 7/TIP 413 compliance
    string is space \x85\u1680\u180E\u200B\u202F\u2060



} 1



test utf-24.6 {unicode space char in regc_locale.c} tip413 {
    # this returns 1 with Unicode 7/TIP 413 compliance
    list [regexp {^[[:space:]]+$} \x85\u1680\u180E\u200B\u202F\u2060] [regexp {^\s+$} \x85\u1680\u180E\u200B\u202F\u2060]

} {1 1}

proc UniCharCaseCmpTest {order one two {constraints {}}} {
    variable count
    test utf-25.$count {Tcl_UniCharNcasecmp} -setup {
	testobj freeallvars


    } -constraints [linsert $constraints 0 teststringobj] -cleanup {

	testobj freeallvars

    } -body {
	teststringobj set 1 $one
	teststringobj set 2 $two
	teststringobj getunicode 1
	teststringobj getunicode 2
	set result [string compare -nocase [teststringobj get 1] [teststringobj get 2]]
	if {$result eq [string map {< -1 = 0 > 1} $order]} {
	    set result ok
	} else {
	    set result "'$one' should be $order '$two' (no case)"
	}
	set result
    } -result ok

    incr count

}
variable count 1
UniCharCaseCmpTest < a b
UniCharCaseCmpTest > b a
UniCharCaseCmpTest > B a
UniCharCaseCmpTest > aBcB abca
UniCharCaseCmpTest < \uFFFF [format %c 0x10000] ucs4
UniCharCaseCmpTest < \uFFFF \U10000		ucs4
UniCharCaseCmpTest > [format %c 0x10000] \uFFFF	ucs4
UniCharCaseCmpTest > \U10000 \uFFFF		ucs4


test utf-26.1 {Tcl_UniCharDString} -setup {
    testobj freeallvars


} -constraints {teststringobj testbytestring} -cleanup {


    testobj freeallvars

} -body {
    teststringobj set 1 foo

    teststringobj getunicode 1
    teststringobj append 1 [testbytestring barsoom\xF2\xC2\x80] 10
    scan [string index [teststringobj get 1] 11] %c
} -result 128


unset count
rename UniCharCaseCmpTest {}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|
<






|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|
|

|
|
<
<
<
<
<
<
<
<
<
<
<
<








|
|

|
|
<
<
<
<
<
<
<
<
<
<
<
<








|
|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















|









|
|






|
|

|
|

|
|

|





|

<
<
|

|
<
|
<
<
<
<
<
<
<
<
<



|
|


|



|




|



|


|
|


|
|


|
|


|
|


|
|


|
|


|
|





|




|
|


|
|



|
|


|




|
|


|

|
|
|
>
>
>
|
>
>
>
|
|
<
>
|
|
<
<
<

>
>
|
>

>
|
|
|


|
<
|
|
|
|
<
|
>
|
>
|
<
|
|
|
|
|
<
<
<
|
|
|
|
>
>
|
>
>
|
>
|
|
>
|
|
|
|
|
|
|
|








167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182



















183
184
185
186
187
188
189
190
191
192
193
194
195












196
197
198
199
200
201
202
203
204
205
206
207
208












209
210
211
212
213
214
215
216
217
218
219
220
221















222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274


275
276
277

278









279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

374
375
376



377
378
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393

394
395
396
397
398

399
400
401
402
403



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
bsCheck \14	12
bsCheck \141	97
bsCheck b\0	98
bsCheck \x	120
bsCheck \xa	10
bsCheck \xA	10
bsCheck \x41	65
bsCheck \x541	65

bsCheck \u	117
bsCheck \uk	117
bsCheck \u41	65
bsCheck \ua	10
bsCheck \uA	10
bsCheck \340	224
bsCheck \ua1	161
bsCheck \u4e21	20001




















test utf-11.1 {Tcl_UtfToUpper} {
    string toupper {}
} {}
test utf-11.2 {Tcl_UtfToUpper} {
    string toupper abc
} ABC
test utf-11.3 {Tcl_UtfToUpper} {
    string toupper \u00e3ab
} \u00c3AB
test utf-11.4 {Tcl_UtfToUpper} {
    string toupper \u01e3ab
} \u01e2AB













test utf-12.1 {Tcl_UtfToLower} {
    string tolower {}
} {}
test utf-12.2 {Tcl_UtfToLower} {
    string tolower ABC
} abc
test utf-12.3 {Tcl_UtfToLower} {
    string tolower \u00c3AB
} \u00e3ab
test utf-12.4 {Tcl_UtfToLower} {
    string tolower \u01e2AB
} \u01e3ab













test utf-13.1 {Tcl_UtfToTitle} {
    string totitle {}
} {}
test utf-13.2 {Tcl_UtfToTitle} {
    string totitle abc
} Abc
test utf-13.3 {Tcl_UtfToTitle} {
    string totitle \u00e3ab
} \u00c3ab
test utf-13.4 {Tcl_UtfToTitle} {
    string totitle \u01f3ab
} \u01f2ab
















test utf-14.1 {Tcl_UtfNcasecmp} {
    string compare -nocase a b
} -1
test utf-14.2 {Tcl_UtfNcasecmp} {
    string compare -nocase b a
} 1
test utf-14.3 {Tcl_UtfNcasecmp} {
    string compare -nocase B a
} 1
test utf-14.4 {Tcl_UtfNcasecmp} {
    string compare -nocase aBcB abca
} 1

test utf-15.1 {Tcl_UniCharToUpper, negative delta} {
    string toupper aA
} AA
test utf-15.2 {Tcl_UniCharToUpper, positive delta} {
    string toupper \u0178\u00ff
} \u0178\u0178
test utf-15.3 {Tcl_UniCharToUpper, no delta} {
    string toupper !
} !

test utf-16.1 {Tcl_UniCharToLower, negative delta} {
    string tolower aA
} aa
test utf-16.2 {Tcl_UniCharToLower, positive delta} {
    string tolower \u0178\u00ff\uA78D\u01c5
} \u00ff\u00ff\u0265\u01c6

test utf-17.1 {Tcl_UniCharToLower, no delta} {
    string tolower !
} !

test utf-18.1 {Tcl_UniCharToTitle, add one for title} {
    string totitle \u01c4
} \u01c5
test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} {
    string totitle \u01c6
} \u01c5
test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} {
    string totitle \u017f
} \u0053
test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} {
    string totitle \u00ff
} \u0178
test utf-18.5 {Tcl_UniCharToTitle, no delta} {
    string totitle !
} !

test utf-19.1 {TclUniCharLen} {
    list [regexp \\d abc456def foo] $foo


} {1 4}

test utf-20.1 {TclUniCharNcmp} {

} {}










test utf-21.1 {TclUniCharIsAlnum} {
    # this returns 1 with Unicode 7 compliance
    string is alnum \u1040\u021f\u0220
} {1}
test utf-21.2 {unicode alnum char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:alnum:]]+$} \u1040\u021f\u0220] [regexp {^\w+$} \u1040\u021f\u0220_\u203f\u2040\u2054\ufe33\ufe34\ufe4d\ufe4e\ufe4f\uff3f]
} {1 1}
test utf-21.3 {unicode print char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:print:]]+$} \ufbc1
} 1
test utf-21.4 {TclUniCharIsGraph} {
    # [Bug 3464428]
    string is graph \u0120
} {1}
test utf-21.5 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {^[[:graph:]]+$} \u0120
} {1}
test utf-21.6 {TclUniCharIsGraph} {
    # [Bug 3464428]
    string is graph \u00a0
} {0}
test utf-21.7 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:graph:]]} \u0020\u00a0\u2028\u2029
} {0}
test utf-21.8 {TclUniCharIsPrint} {
    # [Bug 3464428]
    string is print \u0009
} {0}
test utf-21.9 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \u0009
} {0}
test utf-21.10 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \u0009
} {0}
test utf-21.11 {TclUniCharIsControl} {
    # [Bug 3464428]
    string is control \u0000\u001f\u00ad\u0605\u061c\u180e\u2066\ufeff
} {1}
test utf-21.12 {unicode control char in regc_locale.c} {
    # [Bug 3464428], [Bug a876646efe]
    regexp {^[[:cntrl:]]*$} \u0000\u001f\u00ad\u0605\u061c\u180e\u2066\ufeff
} {1}

test utf-22.1 {TclUniCharIsWordChar} {
    string wordend "xyz123_bar fg" 0
} 10
test utf-22.2 {TclUniCharIsWordChar} {
    string wordend "x\u5080z123_bar\u203c fg" 0
} 10

test utf-23.1 {TclUniCharIsAlpha} {
    # this returns 1 with Unicode 7 compliance
    string is alpha \u021f\u0220\u037f\u052f
} {1}
test utf-23.2 {unicode alpha char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:alpha:]]+$} \u021f\u0220\u037f\u052f
} {1}

test utf-24.1 {TclUniCharIsDigit} {
    # this returns 1 with Unicode 7 compliance
    string is digit \u1040\uabf0
} {1}
test utf-24.2 {unicode digit char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:digit:]]+$} \u1040\uabf0] [regexp {^\d+$} \u1040\uabf0]
} {1 1}

test utf-24.3 {TclUniCharIsSpace} {
    # this returns 1 with Unicode 7 compliance
    string is space \u1680\u180e\u202f
} {1}
test utf-24.4 {unicode space char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:space:]]+$} \u1680\u180e\u202f] [regexp {^\s+$} \u1680\u180e\u202f]
} {1 1}

testConstraint teststringobj [llength [info commands teststringobj]]

test utf-25.1 {Tcl_UniCharNcasecmp} -constraints teststringobj \
    -setup {
	testobj freeallvars
    } \
    -body {
	teststringobj set 1 a
	teststringobj set 2 b
	teststringobj getunicode 1
	teststringobj getunicode 2

	string compare -nocase [teststringobj get 1] [teststringobj get 2]
    } \
    -cleanup {



	testobj freeallvars
    } \
    -result -1
test utf-25.2 {Tcl_UniCharNcasecmp} -constraints teststringobj \
    -setup {
	testobj freeallvars
    } \
    -body {
	teststringobj set 1 b
	teststringobj set 2 a
	teststringobj getunicode 1
	teststringobj getunicode 2
	string compare -nocase [teststringobj get 1] [teststringobj get 2]

    } \
    -cleanup {
	testobj freeallvars
    } \

    -result 1
test utf-25.3 {Tcl_UniCharNcasecmp} -constraints teststringobj \
    -setup {
	testobj freeallvars
    } \

    -body {
	teststringobj set 1 B
	teststringobj set 2 a
	teststringobj getunicode 1
	teststringobj getunicode 2



	string compare -nocase [teststringobj get 1] [teststringobj get 2]
    } \
    -cleanup {
	testobj freeallvars
    } \
    -result 1

test utf-25.4 {Tcl_UniCharNcasecmp} -constraints teststringobj \
    -setup {
	testobj freeallvars
    } \
    -body {
	teststringobj set 1 aBcB
	teststringobj set 2 abca
	teststringobj getunicode 1
	teststringobj getunicode 2
	string compare -nocase [teststringobj get 1] [teststringobj get 2]
    } \
    -cleanup {
	testobj freeallvars
    } \
    -result 1

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/util.test.

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
} {a c}
test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
    # Check for Bug #227512.  If this violates C isspace, then it returns \xc3.
    concat \xe0
} \xe0
test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj {
    # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the
    # symptoms was Bug #2055782.
    testconcatobj
} {}
test util-4.8 {Tcl_ConcatObj - [Bug 26649439c7]} {
    concat [list foo] [list #]
} {foo {#}}

proc Wrapper_Tcl_StringMatch {pattern string} {
    # Forces use of Tcl_StringMatch, not Tcl_UniCharCaseMatch
    switch -glob -- $string $pattern {return 1} default {return 0}
}
test util-5.1 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch ab*c abc







|


<
<
<







199
200
201
202
203
204
205
206
207
208



209
210
211
212
213
214
215
} {a c}
test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
    # Check for Bug #227512.  If this violates C isspace, then it returns \xc3.
    concat \xe0
} \xe0
test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj {
    # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the
    # symptoms was Bug #2055782. 
    testconcatobj
} {}




proc Wrapper_Tcl_StringMatch {pattern string} {
    # Forces use of Tcl_StringMatch, not Tcl_UniCharCaseMatch
    switch -glob -- $string $pattern {return 1} default {return 0}
}
test util-5.1 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch ab*c abc
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
} 1
test util-5.50 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *. ""
} 0
test util-5.51 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch "" ""
} 1
test util-5.52 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch \[a\u0000 a\x80
} 0


test util-6.1 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 12
} -body {
    concat x[expr 1.4]
} -cleanup {







<
<
<
<







374
375
376
377
378
379
380




381
382
383
384
385
386
387
} 1
test util-5.50 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *. ""
} 0
test util-5.51 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch "" ""
} 1





test util-6.1 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 12
} -body {
    concat x[expr 1.4]
} -cleanup {
506
507
508
509
510
511
512





513
514
515
516
517
518

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
    testdstring free
    testdstring append {\ } -1
    testdstring append \{ -1
    testdstring element foo
    llength [testdstring get]
} 2
test util-8.5 {TclNeedSpace - correct UTF8 handling} testdstring {





    testdstring free
    testdstring append {\\ } -1
    testdstring element foo
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 6}
test util-8.6 {TclNeedSpace - correct UTF8 handling} testdstring {

    testdstring free
    testdstring append {\\ } -1
    testdstring append \{ -1
    testdstring element foo
    testdstring append \} -1
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 8}
test util-8.7 {TclNeedSpace - watch out for escaped space} {
    testdstring free
    testdstring append {\ } -1
    testdstring start
    testdstring end

    # Should make {\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 3]
} {2 \{}
test util-8.8 {TclNeedSpace - watch out for escaped space} {
    testdstring free
    testdstring append {\\ } -1
    testdstring start
    testdstring end

    # Should make {\\ {}}
    list [llength [testdstring get]] [string index [testdstring get] 3]
} {2 \{}
test util-8.9 {TclNeedSpace - watch out for escaped space} {
    testdstring free
    testdstring append {\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 5]
} {2 \{}
test util-8.10 {TclNeedSpace - watch out for escaped space} {
    testdstring free
    testdstring append {\\\\\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\\\\\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 9]
} {2 \{}
test util-8.11 {TclNeedSpace - watch out for escaped space} {
    testdstring free
    testdstring append {\\\\\\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\\\\\\ {}}
    list [llength [testdstring get]] [string index [testdstring get] 9]
} {2 \{}

test util-9.0.0 {TclGetIntForIndex} {
    string index abcd 0
} a
test util-9.0.1 {TclGetIntForIndex} {
    string index abcd 0x0
} a







>
>
>
>
>




|

>






|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524













































525
526
527
528
529
530
531
    testdstring free
    testdstring append {\ } -1
    testdstring append \{ -1
    testdstring element foo
    llength [testdstring get]
} 2
test util-8.5 {TclNeedSpace - correct UTF8 handling} testdstring {
    # Note that in this test TclNeedSpace actually gets it wrong,
    # claiming we need a space when we really do not.  Extra space
    # between list elements is harmless though, and better to have
    # extra space in really weird string reps of lists, than to
    # invest the effort required to make TclNeedSpace foolproof.
    testdstring free
    testdstring append {\\ } -1
    testdstring element foo
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 7}
test util-8.6 {TclNeedSpace - correct UTF8 handling} testdstring {
    # Another example of TclNeedSpace harmlessly getting it wrong.
    testdstring free
    testdstring append {\\ } -1
    testdstring append \{ -1
    testdstring element foo
    testdstring append \} -1
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 9}














































test util-9.0.0 {TclGetIntForIndex} {
    string index abcd 0
} a
test util-9.0.1 {TclGetIntForIndex} {
    string index abcd 0x0
} a
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
    string index abcdefghijk 0xa
} k
test util-9.1.3 {TclGetIntForIndex} {
    string index abcdefghijk { 0xa }
} k
test util-9.2.0 {TclGetIntForIndex} {
    string index abcd end
} d
test util-9.2.1 {TclGetIntForIndex} -body {
    string index abcd { end}
} -returnCodes error -match glob -result *
test util-9.2.2 {TclGetIntForIndex} -body {
    string index abcd {end }
} -returnCodes error -match glob -result *
test util-9.3 {TclGetIntForIndex} {







|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    string index abcdefghijk 0xa
} k
test util-9.1.3 {TclGetIntForIndex} {
    string index abcdefghijk { 0xa }
} k
test util-9.2.0 {TclGetIntForIndex} {
    string index abcd end
} d 
test util-9.2.1 {TclGetIntForIndex} -body {
    string index abcd { end}
} -returnCodes error -match glob -result *
test util-9.2.2 {TclGetIntForIndex} -body {
    string index abcd {end }
} -returnCodes error -match glob -result *
test util-9.3 {TclGetIntForIndex} {
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
	binary scan [binary format q [expr double($input)]] wu x
	lappend r [format %#llx $x]
	binary scan [binary format q [expr double(-$input)]] wu x
	lappend r [format %#llx $x]
    }
    set r
} [list {*}{
    0x43fffffffffffffc 0xc3fffffffffffffc
    0x43fffffffffffffc 0xc3fffffffffffffc
    0x43fffffffffffffd 0xc3fffffffffffffd
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43ffffffffffffff 0xc3ffffffffffffff
    0x4400000000000000 0xc400000000000000







|







3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
	binary scan [binary format q [expr double($input)]] wu x
	lappend r [format %#llx $x]
	binary scan [binary format q [expr double(-$input)]] wu x
	lappend r [format %#llx $x]
    }
    set r
} [list {*}{
    0x43fffffffffffffc 0xc3fffffffffffffc 
    0x43fffffffffffffc 0xc3fffffffffffffc
    0x43fffffffffffffd 0xc3fffffffffffffd
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43ffffffffffffff 0xc3ffffffffffffff
    0x4400000000000000 0xc400000000000000

Changes to tests/winDde.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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# This file tests the tclWinDde.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    #tcltest::configure -verbose {pass start}
    namespace import -force ::tcltest::*
}

testConstraint debug [::tcl::pkgconfig get debug]
testConstraint dde 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::ddever [package require dde 1.4.3]
	    set ::ddelib [info loaded "" Dde]}]} {
	testConstraint dde 1
    }
}


# -------------------------------------------------------------------------
# Setup a script for a test server
#

set scriptName [makeFile {} script1.tcl]

proc createChildProcess {ddeServerName args} {
    file delete -force $::scriptName

    set f [open $::scriptName w+]
    puts $f [list set ddeServerName $ddeServerName]
    puts $f [list load $::ddelib Dde]
    puts $f {
        # DDE child server -
        #
	if {"::tcltest" ni [namespace children]} {
	    package require tcltest 2.5
	    namespace import -force ::tcltest::*
	}

        # If an error occurs during the tests, this process may end up not
        # being closed down. To deal with this we create a 30s timeout.
        proc ::DoTimeout {} {
            global done ddeServerName
            set done 1
            puts "winDde.test child process $ddeServerName timed out."
            flush stdout
        }
        set timeout [after 30000 ::DoTimeout]

        # Define a restricted handler.
        proc Handler1 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            if {$cmd == ""} {
                set cmd "null data"
            }
            puts $cmd ; flush stdout
            return
        }
        proc Handler2 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [uplevel \#0 $cmd] ; flush stdout
            return
        }
        proc Handler3 {prefix cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [list $prefix $cmd] ; flush stdout
            return
        }
    }
    # set the dde server name to the supplied argument.

    puts $f [list dde servername {*}$args -- $ddeServerName]



    puts $f {
        # run the server and handle final cleanup.
        after 200;# give dde a chance to get going.
	puts ready
        flush stdout
	vwait done
	# allow enough time for the calling process to
	# claim all results, to avoid spurious "server did
	# not respond"
	after 200 {set reallyDone 1}
	vwait reallyDone
	exit
    }
    close $f

    # run the child server script.
    set f [open |[list [interpreter] $::scriptName] r]
    fconfigure $f -buffering line
    gets $f line
    return $f
}

# -------------------------------------------------------------------------
test winDde-1.0 {check if we are testing the right dll} {win dde} {
    set ::ddever
} {1.4.3}

test winDde-1.1 {Settings the server's topic name} -constraints dde -body {
    list [dde servername foobar] [dde servername] [dde servername self]
} -result {foobar foobar self}

test winDde-2.1 {Checking for other services} -constraints dde -body {
    expr {[llength [dde services {} {}]] >= 0}
} -result 1
test winDde-2.2 {Checking for existence, with service and topic specified} \
	-constraints dde -body {
    llength [dde services TclEval self]
} -result 1
test winDde-2.3 {Checking for existence, with only the service specified} \
	-constraints dde -body {
    expr {[llength [dde services TclEval {}]] >= 1}
} -result 1
test winDde-2.4 {Checking for existence, with only the topic specified} \
	-constraints dde -body {
    expr {[llength [dde services {} self]] >= 1}
} -result 1

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

test winDde-3.1 {DDE execute locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    set \xe1
} -result foo
test winDde-3.2 {DDE execute -async locally} -constraints dde -body {
    set \xe1 ""
    dde execute -async TclEval self [list set \xe1 foo]
    update
    set \xe1
} -result foo
test winDde-3.3 {DDE request locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    dde request TclEval self \xe1
} -result foo
test winDde-3.4 {DDE eval locally} -constraints dde -body {
    set \xe1 ""
    dde eval self set \xe1 foo
} -result foo
test winDde-3.5 {DDE request locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    dde request -binary TclEval self \xe1
} -result "foo\x00"
# Set variable a to A with diaeresis (unicode C4) by relying on the fact
# that utf-8 is sent (e.g. "c3 84" on the wire)
test winDde-3.6 {DDE request utf-8} -constraints dde -body {
    set \xe1 "not set"
    dde execute TclEval self "set \xe1 \xc4"
    scan [set \xe1] %c
} -result 196
# Set variable a to A with diaeresis (unicode C4) using binary execute
# and compose utf-8 (e.g. "c3 84" ) manualy
test winDde-3.7 {DDE request binary} -constraints dde -body {
    set \xe1 "not set"
    dde execute -binary TclEval self [list set \xc3\xa1 \xc3\x84\x00]
    scan [set \xe1] %c
} -result 196
test winDde-3.8 {DDE poke locally} -constraints {dde debug} -body {
    set \xe1 ""
    dde poke TclEval self \xe1 \xc4
    dde request TclEval self \xe1
} -result \xc4
test winDde-3.9 {DDE poke -binary locally} -constraints {dde debug} -body {
    set \xe1 ""
    dde poke -binary TclEval self \xe1 \xc3\x84\x00
    dde request TclEval self \xe1
} -result \xc4

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

test winDde-4.1 {DDE execute remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.1
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xe1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result ""
test winDde-4.2 {DDE execute async remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.2
    set child [createChildProcess $name]
    dde execute -async TclEval $name [list set \xe1 foo]
    update
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result ""
test winDde-4.3 {DDE request remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.3
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xe1 foo]
    set \xe1 [dde request TclEval $name \xe1]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result foo
test winDde-4.4 {DDE eval remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.4
    set child [createChildProcess $name]
    set \xe1 [dde eval $name set \xe1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
}  -result foo
test winDde-4.5 {DDE poke remotely} -constraints {dde debug stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.5
    set child [createChildProcess $name]
    dde poke TclEval $name \xe1 foo
    set \xe1 [dde request TclEval $name \xe1]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result foo

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

test winDde-5.1 {check for bad arguments} -constraints dde -body {
    dde execute "" "" "" ""
} -returnCodes error -result {wrong # args: should be "dde execute ?-async? ?-binary? serviceName topicName value"}
test winDde-5.2 {check for bad arguments} -constraints dde -body {
    dde execute -binary "" "" ""
} -returnCodes error -result {cannot execute null data}
test winDde-5.3 {check for bad arguments} -constraints dde -body {
    dde execute -foo "" "" ""
} -returnCodes error -result {wrong # args: should be "dde execute ?-async? ?-binary? serviceName topicName value"}
test winDde-5.4 {DDE eval bad arguments} -constraints dde -body {
    dde eval "" "foo"
} -returnCodes error -result {invalid service name ""}

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

test winDde-6.1 {DDE servername bad arguments} -constraints dde -body {
    dde servername -z -z -z
} -returnCodes error -result {bad option "-z": must be -force, -handler, or --}
test winDde-6.2 {DDE servername set name} -constraints dde -body {
    dde servername -- winDde-6.2
} -result {winDde-6.2}
test winDde-6.3 {DDE servername set exact name} -constraints dde -body {
    dde servername -force winDde-6.3
} -result {winDde-6.3}
test winDde-6.4 {DDE servername set exact name} -constraints dde -body {
    dde servername -force -- winDde-6.4
} -result {winDde-6.4}
test winDde-6.5 {DDE remote servername collision} -constraints {dde stdio} -setup {
    set name ch\xEDld-6.5
    set child [createChildProcess $name]
} -body {
    dde servername -- $name
} -cleanup {
    dde execute TclEval $name {set done 1}
    update
} -result "ch\xEDld-6.5 #2"
test winDde-6.6 {DDE remote servername collision force} -constraints {dde stdio} -setup {
    set name ch\xEDld-6.6
    set child [createChildProcess $name]
} -body {
    dde servername -force -- $name
} -cleanup {
    dde execute TclEval $name {set done 1}
    update
} -result "ch\xEDld-6.6"

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

test winDde-7.1 {Load DDE in slave interpreter} -constraints dde -setup {
    interp create slave
} -body {
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.1]
} -cleanup {
    interp delete slave
} -result {dde-interp-7.1}
test winDde-7.2 {DDE slave cleanup} -constraints dde -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.5]
    interp delete slave
} -body {
    dde services TclEval {}
    set s [dde services TclEval {}]
    set m [list [list TclEval dde-interp-7.5]]
    if {$m in $s} {
	set s
    }
} -result {}
test winDde-7.3 {DDE present in slave interp} -constraints dde -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.3]
} -body {
    dde services TclEval dde-interp-7.3
} -cleanup {
    interp delete slave
} -result {{TclEval dde-interp-7.3}}
test winDde-7.4 {interp name collision with -force} -constraints dde -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.4]
} -body {
    dde servername -force -- dde-interp-7.4
} -cleanup {
    interp delete slave
} -result {dde-interp-7.4}
test winDde-7.5 {interp name collision without -force} -constraints dde -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.5]
} -body {
    dde servername -- dde-interp-7.5
} -cleanup {
    interp delete slave
} -result "dde-interp-7.5 #2"

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

test winDde-8.1 {Safe DDE load} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
} -body {
    slave eval dde servername slave
} -cleanup {
    interp delete slave
} -returnCodes error -result {invalid command name "dde"}
test winDde-8.2 {Safe DDE set servername} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
} -body {
    slave invokehidden dde servername slave
} -cleanup {interp delete slave} -result {slave}
test winDde-8.3 {Safe DDE check handler required for eval} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    catch {dde eval slave set a 1} msg
} -cleanup {interp delete slave} -result {1}
test winDde-8.4 {Safe DDE check that execute is denied} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    slave eval set a 1
    dde execute TclEval slave {set a 2}
    slave eval set a
} -cleanup {interp delete slave} -result 1
test winDde-8.5 {Safe DDE check that request is denied} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    slave eval set a 1
    dde request TclEval slave a
} -cleanup {
    interp delete slave
} -returnCodes error -result {remote server cannot handle this command}
test winDde-8.6 {Safe DDE assign handler procedure} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
} -body {
    slave invokehidden dde servername -handler DDEACCEPT slave
} -cleanup {interp delete slave} -result slave
test winDde-8.7 {Safe DDE check simple command} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave set x 1
} -cleanup {interp delete slave} -result {set x 1}
test winDde-8.8 {Safe DDE check non-list command} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    set s "c:\\Program Files\\Microsoft Visual Studio\\"
    dde eval slave $s
    string equal [slave eval set DDECMD] $s
} -cleanup {interp delete slave} -result 1
test winDde-8.9 {Safe DDE check command evaluation} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave set \xe1 1
    slave eval set \xe1
} -cleanup {interp delete slave} -result 1
test winDde-8.10 {Safe DDE check command evaluation (2)} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave [list set x 1]
    slave eval set x
} -cleanup {interp delete slave} -result 1
test winDde-8.11 {Safe DDE check command evaluation (3)} -constraints dde -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave [list [list set x 1]]
    slave eval set x
} -cleanup {interp delete slave} -returnCodes error -result {invalid command name "set x 1"}

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

test winDde-9.1 {External safe DDE check string passing} -constraints {dde stdio} -setup {
    set name ch\xEDld-9.1
    set child [createChildProcess $name -handler Handler1]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result {set x 1}
test winDde-9.2 {External safe DDE check command evaluation} -constraints {dde stdio} -setup {
    set name ch\xEDld-9.2
    set child [createChildProcess $name -handler Handler2]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result 1
test winDde-9.3 {External safe DDE check prefixed arguments} -constraints {dde stdio} -setup {
    set name ch\xEDld-9.3
    set child [createChildProcess $name -handler [list Handler3 ARG]]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result {ARG {set x 1}}
test winDde-9.4 {External safe DDE check null data passing} -constraints {dde stdio} -setup {
    set name ch\xEDld-9.4
    set child [createChildProcess $name -handler Handler1]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde execute TclEval $name ""
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result {null data}

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

#cleanup
#catch {interp delete $slave};           # ensure we clean up the slave.
file delete -force $::scriptName
::tcltest::cleanupTests











|
|




<




|
|











|




|



|
|


|









|



<
<
<
|




|









>
|
>
>
>









|




|








<
<
<

|

|

|
|
|

|

|

|
|
|

|
|
|



|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
|
|
|

|


|
|
|
|
|

|



|
|
|
|
|

|
|


|
|
|
|
|

|


|
|
<
<
<
<
<
<
<
<
<
<



|

|
|
|

|

|
|





|


|


|


|


|
|






|
|
|






|



|







|








|



|








|








|











|







|





|






|








|









|






|







|









|





|
|

|








|











|
|
|










|
|
|










|
|
|










<
<
<
<
<
<
<
<
<
<
<
<
<







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154






















155


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193










194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429













430
431
432
433
434
435
436
# This file tests the tclWinDde.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    #tcltest::configure -verbose {pass start}
    namespace import -force ::tcltest::*
}


testConstraint dde 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    package require dde
	    set ::ddelib [lindex [package ifneeded dde 1.3.3] 1]}]} {
	testConstraint dde 1
    }
}


# -------------------------------------------------------------------------
# Setup a script for a test server
#

set scriptName [makeFile {} script1.tcl]

proc createChildProcess {ddeServerName {handler {}}} {
    file delete -force $::scriptName

    set f [open $::scriptName w+]
    puts $f [list set ddeServerName $ddeServerName]
    puts $f [list load $::ddelib dde]
    puts $f {
        # DDE child server -
        #
	if {[lsearch [namespace children] ::tcltest] == -1} {
	    package require tcltest
	    namespace import -force ::tcltest::*
	}
        
        # If an error occurs during the tests, this process may end up not
        # being closed down. To deal with this we create a 30s timeout.
        proc ::DoTimeout {} {
            global done ddeServerName
            set done 1
            puts "winDde.test child process $ddeServerName timed out."
            flush stdout
        }
        set timeout [after 30000 ::DoTimeout]
        
        # Define a restricted handler.
        proc Handler1 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}



            puts $cmd ; flush stdout 
            return
        }
        proc Handler2 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [uplevel \#0 $cmd] ; flush stdout 
            return
        }
        proc Handler3 {prefix cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [list $prefix $cmd] ; flush stdout
            return
        }
    }
    # set the dde server name to the supplied argument.
    if {$handler == {}} {
        puts $f [list dde servername $ddeServerName]
    } else {
        puts $f [list dde servername -handler $handler -- $ddeServerName]
    }        
    puts $f {
        # run the server and handle final cleanup.
        after 200;# give dde a chance to get going.
	puts ready
        flush stdout
	vwait done
	# allow enough time for the calling process to
	# claim all results, to avoid spurious "server did
	# not respond"
	after 200 { set reallyDone 1 }
	vwait reallyDone
	exit
    }
    close $f
    
    # run the child server script.
    set f [open |[list [interpreter] $::scriptName] r]
    fconfigure $f -buffering line
    gets $f line
    return $f
}

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




test winDde-1.1 {Settings the server's topic name} {win dde} {
    list [dde servername foobar] [dde servername] [dde servername self]
}  {foobar foobar self}

test winDde-2.1 {Checking for other services} {win dde} {
    expr [llength [dde services {} {}]] >= 0
} 1
test winDde-2.2 {Checking for existence, with service and topic specified} \
	{win dde} {
    llength [dde services TclEval self]
} 1
test winDde-2.3 {Checking for existence, with only the service specified} \
	{win dde} {
    expr [llength [dde services TclEval {}]] >= 1
} 1
test winDde-2.4 {Checking for existence, with only the topic specified} \
	{win dde} {
    expr [llength [dde services {} self]] >= 1
} 1

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

test winDde-3.1 {DDE execute locally} {win dde} {
    set a ""
    dde execute TclEval self {set a "foo"}
    set a
} foo
test winDde-3.2 {DDE execute -async locally} {win dde} {
    set a ""
    dde execute -async TclEval self {set a "foo"}
    update
    set a
} foo
test winDde-3.3 {DDE request locally} {win dde} {
    set a ""
    dde execute TclEval self {set a "foo"}
    dde request TclEval self a
} foo
test winDde-3.4 {DDE eval locally} {win dde} {
    set a ""
    dde eval self set a "foo"
} foo
test winDde-3.5 {DDE request locally} {win dde} {
    set a ""
    dde execute TclEval self {set a "foo"}
    dde request -binary TclEval self a
} "foo\x00"

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

























test winDde-4.1 {DDE execute remotely} {stdio win dde} {
    set a ""
    set name child-4.1
    set child [createChildProcess $name]
    dde execute TclEval $name {set a "foo"}
    dde execute TclEval $name {set done 1}
    update
    set a
} ""
test winDde-4.2 {DDE execute async remotely} {stdio win dde} {
    set a ""
    set name child-4.2
    set child [createChildProcess $name]
    dde execute -async TclEval $name {set a "foo"}
    update
    dde execute TclEval $name {set done 1}
    update
    set a
} ""
test winDde-4.3 {DDE request remotely} {stdio win dde} {
    set a ""
    set name chile-4.3
    set child [createChildProcess $name]
    dde execute TclEval $name {set a "foo"}
    set a [dde request TclEval $name a]
    dde execute TclEval $name {set done 1}
    update
    set a
} foo
test winDde-4.4 {DDE eval remotely} {stdio win dde} {
    set a ""
    set name child-4.4
    set child [createChildProcess $name]
    set a [dde eval $name set a "foo"]
    dde execute TclEval $name {set done 1}
    update
    set a
} foo











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

test winDde-5.1 {check for bad arguments} -constraints {win dde} -body {
    dde execute "" "" "" ""
} -returnCodes error -result {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
test winDde-5.2 {check for bad arguments} -constraints {win dde} -body {
    dde execute "" "" ""
} -returnCodes error -result {cannot execute null data}
test winDde-5.3 {check for bad arguments} -constraints {win dde} -body {
    dde execute -foo "" "" ""
} -returnCodes error -result {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
test winDde-5.4 {DDE eval bad arguments} -constraints {win dde} -body {
    dde eval "" "foo"
} -returnCodes error -result {invalid service name ""}

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

test winDde-6.1 {DDE servername bad arguments} -constraints {win dde} -body {
    dde servername -z -z -z
} -returnCodes error -result {bad option "-z": must be -force, -handler, or --}
test winDde-6.2 {DDE servername set name} -constraints {win dde} -body {
    dde servername -- winDde-6.2
} -result {winDde-6.2}
test winDde-6.3 {DDE servername set exact name} -constraints {win dde} -body {
    dde servername -force winDde-6.3
} -result {winDde-6.3}
test winDde-6.4 {DDE servername set exact name} -constraints {win dde} -body {
    dde servername -force -- winDde-6.4
} -result {winDde-6.4}
test winDde-6.5 {DDE remote servername collision} -constraints {stdio win dde} -setup {
    set name child-6.5
    set child [createChildProcess $name]
} -body {
    dde servername -- $name
} -cleanup {
    dde execute TclEval $name {set done 1}
    update
} -result "child-6.5 #2"
test winDde-6.6 {DDE remote servername collision force} -constraints {stdio win dde} -setup {
    set name child-6.6
    set child [createChildProcess $name]
} -body {
    dde servername -force -- $name
} -cleanup {
    dde execute TclEval $name {set done 1}
    update
} -result {child-6.6}

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

test winDde-7.1 {Load DDE in slave interpreter } -constraints {win dde} -setup {
    interp create slave
} -body {
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.1]
} -cleanup {
    interp delete slave
} -result {dde-interp-7.1}
test winDde-7.2 {DDE slave cleanup} -constraints {win dde} -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.5]
    interp delete slave
} -body {
    dde services TclEval {}
    set s [dde services TclEval {}]
    set m [list [list TclEval dde-interp-7.5]]
    if {[lsearch -exact $s $m] != -1} {
	set s
    }
} -result {}
test winDde-7.3 {DDE present in slave interp} -constraints {win dde} -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.3]
} -body {
    dde services TclEval dde-interp-7.3
} -cleanup {
    interp delete slave
} -result {{TclEval dde-interp-7.3}}
test winDde-7.4 {interp name collision with -force} -constraints {win dde} -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.4]
} -body {
    dde servername -force -- dde-interp-7.4
} -cleanup {
    interp delete slave
} -result {dde-interp-7.4}
test winDde-7.5 {interp name collision without -force} -constraints {win dde} -setup {
    interp create slave
    slave eval [list load $::ddelib Dde]
    slave eval [list dde servername -- dde-interp-7.5]
} -body {
    dde servername -- dde-interp-7.5
} -cleanup {
    interp delete slave
} -result "dde-interp-7.5 #2"

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

test winDde-8.1 {Safe DDE load} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
} -body {
    slave eval dde servername slave
} -cleanup {
    interp delete slave
} -returnCodes error -result {invalid command name "dde"}
test winDde-8.2 {Safe DDE set servername} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
} -body {
    slave invokehidden dde servername slave
} -cleanup {interp delete slave} -result {slave}
test winDde-8.3 {Safe DDE check handler required for eval} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    catch {dde eval slave set a 1} msg
} -cleanup {interp delete slave} -result {1}
test winDde-8.4 {Safe DDE check that execute is denied} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    slave eval set a 1
    dde execute TclEval slave {set a 2}
    slave eval set a
} -cleanup {interp delete slave} -result 1
test winDde-8.5 {Safe DDE check that request is denied} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave invokehidden dde servername slave
} -body {
    slave eval set a 1
    dde request TclEval slave a
} -cleanup {
    interp delete slave
} -returnCodes error -result {remote server cannot handle this command}
test winDde-8.6 {Safe DDE assign handler procedure} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
} -body {
    slave invokehidden dde servername -handler DDEACCEPT slave
} -cleanup {interp delete slave} -result slave
test winDde-8.7 {Safe DDE check simple command} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave set x 1
} -cleanup {interp delete slave} -result {set x 1}
test winDde-8.8 {Safe DDE check non-list command} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    set s "c:\\Program Files\\Microsoft Visual Studio\\"
    dde eval slave $s
    string equal [slave eval set DDECMD] $s
} -cleanup {interp delete slave} -result 1
test winDde-8.9 {Safe DDE check command evaluation} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave set x 1
    slave eval set x
} -cleanup {interp delete slave} -result 1
test winDde-8.10 {Safe DDE check command evaluation (2)} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave [list set x 1]
    slave eval set x
} -cleanup {interp delete slave} -result 1
test winDde-8.11 {Safe DDE check command evaluation (3)} -constraints {win dde} -setup {
    interp create -safe slave
    slave invokehidden load $::ddelib Dde
    slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    slave invokehidden dde servername -handler DDEACCEPT slave
} -body {
    dde eval slave [list [list set x 1]]
    slave eval set x
} -cleanup {interp delete slave} -returnCodes error -result {invalid command name "set x 1"}

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

test winDde-9.1 {External safe DDE check string passing} -constraints {win dde stdio} -setup {
    set name child-9.1
    set child [createChildProcess $name Handler1]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result {set x 1}
test winDde-9.2 {External safe DDE check command evaluation} -constraints {win dde stdio} -setup {
    set name child-9.2
    set child [createChildProcess $name Handler2]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result 1
test winDde-9.3 {External safe DDE check prefixed arguments} -constraints {win dde stdio} -setup {
    set name child-9.3
    set child [createChildProcess $name [list Handler3 ARG]]
    file copy -force script1.tcl dde-script.tcl
} -body {
    dde eval $name set x 1
    gets $child line
    set line
} -cleanup {
    dde execute TclEval $name stop
    update
    file delete -force -- dde-script.tcl
} -result {ARG {set x 1}}














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

#cleanup
#catch {interp delete $slave};           # ensure we clean up the slave.
file delete -force $::scriptName
::tcltest::cleanupTests

Changes to tests/winFCmd.test.

49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
	if {$x != ""} {
	    catch {file delete -force -- {*}$x}
	}
    }
}

if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) >= 5.0} {

	testConstraint winVista 1
    } elseif {$::tcl_platform(osVersion) >= 4.0} {
	testConstraint winXP 1
    }
}

# find a CD-ROM so we can test read-only filesystems.

proc findfile {dir} {







|
>

|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	if {$x != ""} {
	    catch {file delete -force -- {*}$x}
	}
    }
}

if {[testConstraint win]} {
    set major [string index $tcl_platform(osVersion) 0]
    if {$major > 5} {
	testConstraint winVista 1
    } elseif {$major == 5} {
	testConstraint winXP 1
    }
}

# find a CD-ROM so we can test read-only filesystems.

proc findfile {dir} {
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
test winFCmd-16.9 {Windows file normalization} {win} {
    file norm /bar/foo
} "${d}:/bar/foo"
if {$d eq "C"} { set dd "D" } else { set dd "C" }
test winFCmd-16.10 {Windows file normalization} {win} {
    file norm ${dd}:foo
} "${dd}:/foo"
test winFCmd-16.11 {Windows file normalization} -body {

    cd ${d}:
    cd $cdrom
    cd ${d}:
    cd $cdrom
    # Must not crash
    set result "no crash"
} -constraints {win cdrom} -cleanup {
    cd $pwd
} -result {no crash}

test winFCmd-16.12 {Windows file normalization - no crash} \
  -constraints win -setup {
    set oldhome ""
    catch {set oldhome $::env(HOME)}
} -body {
    set expectedResult [file normalize ${d}:]
    set ::env(HOME) ${d}:
    cd
    # At one point this led to an infinite recursion in Tcl
    set result [pwd]; # <- Must not crash
    set result "no crash"
} -cleanup {
    set ::env(HOME) $oldhome
    cd $pwd
} -result {no crash}

test winFCmd-16.13 {Windows file normalization} -constraints win -setup {
    set oldhome ""
    catch {set oldhome $::env(HOME)}
} -body {
    # Test 'cd' normalization when HOME is absolute
    set expectedResult [file normalize ${d}:/]
    set ::env(HOME) ${d}:/







|
>






|


>















>







1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
test winFCmd-16.9 {Windows file normalization} {win} {
    file norm /bar/foo
} "${d}:/bar/foo"
if {$d eq "C"} { set dd "D" } else { set dd "C" }
test winFCmd-16.10 {Windows file normalization} {win} {
    file norm ${dd}:foo
} "${dd}:/foo"
test winFCmd-16.11 {Windows file normalization} -constraints {win cdrom} \
-body {
    cd ${d}:
    cd $cdrom
    cd ${d}:
    cd $cdrom
    # Must not crash
    set result "no crash"
} -cleanup {
    cd $pwd
} -result {no crash}

test winFCmd-16.12 {Windows file normalization - no crash} \
  -constraints win -setup {
    set oldhome ""
    catch {set oldhome $::env(HOME)}
} -body {
    set expectedResult [file normalize ${d}:]
    set ::env(HOME) ${d}:
    cd
    # At one point this led to an infinite recursion in Tcl
    set result [pwd]; # <- Must not crash
    set result "no crash"
} -cleanup {
    set ::env(HOME) $oldhome
    cd $pwd
} -result {no crash}

test winFCmd-16.13 {Windows file normalization} -constraints win -setup {
    set oldhome ""
    catch {set oldhome $::env(HOME)}
} -body {
    # Test 'cd' normalization when HOME is absolute
    set expectedResult [file normalize ${d}:/]
    set ::env(HOME) ${d}:/
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124

1125
1126
1127

1128
1129
1130

1131
1132
1133

1134
1135
1136

1137
1138
1139

1140
1141
1142

1143
1144
1145

1146
1147
1148

1149
1150
1151

1152
1153
1154

1155
1156
1157

1158
1159
1160

1161
1162
1163
1164

1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229

test winFCmd-17.1 {Windows bad permissions cd} -constraints win -body {
    set d {}
    foreach dd {c:/ d:/ e:/} {
	eval lappend d [glob -nocomplain \
	  -types hidden -dir $dd "System Volume Information"]
    }
    # Old versions of Tcl gave a misleading error that the
    # directory in question didn't exist.
    if {[llength $d] && [catch {cd [lindex $d 0]} err]} {
	regsub ".*: " $err "" err
	set err
    } else {
        set err "permission denied"
    }
} -cleanup {
    cd $pwd
} -result "permission denied"

cd $pwd
unset d dd pwd

test winFCmd-18.1 {Windows reserved path names} -constraints win -body {
    file pathtype com1
} -result "absolute"

test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body {
    file pathtype com4
} -result "absolute"

test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body {
    file pathtype com9
} -result "absolute"

test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body {
    file pathtype lpt3
} -result "absolute"

test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body {
    file pathtype lpt9
} -result "absolute"

test winFCmd-18.1.6 {Windows reserved path names} -constraints win -body {
    file pathtype nul
} -result "absolute"

test winFCmd-18.1.7 {Windows reserved path names} -constraints win -body {
    file pathtype null
} -result "relative"

test winFCmd-18.2 {Windows reserved path names} -constraints win -body {
    file pathtype com1:
} -result "absolute"

test winFCmd-18.3 {Windows reserved path names} -constraints win -body {
    file pathtype COM1
} -result "absolute"

test winFCmd-18.4 {Windows reserved path names} -constraints win -body {
    file pathtype CoM1:
} -result "absolute"

test winFCmd-18.5 {Windows reserved path names} -constraints win -body {
    file normalize com1:
} -result COM1

test winFCmd-18.6 {Windows reserved path names} -constraints win -body {
    file normalize COM1:
} -result COM1

test winFCmd-18.7 {Windows reserved path names} -constraints win -body {
    file normalize cOm1
} -result COM1

test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
    file normalize cOm1:
} -result COM1


test winFCmd-19.1 {Windows extended path names} -constraints nt -body {
    file normalize //?/c:/windows/win.ini
} -result //?/c:/windows/win.ini

test winFCmd-19.2 {Windows extended path names} -constraints nt -body {
    file normalize //?/c:/windows/../windows/win.ini
} -result //?/c:/windows/win.ini

test winFCmd-19.3 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.4 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.5 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 200].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.6 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.7 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {} [list tcl[pid].tmp]]

test winFCmd-19.8 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f







|

















>



>



>



>



>



>



>



>



>



>



>



>



>



>




>



>











>











>

|





|


|
>











>











>







1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254

test winFCmd-17.1 {Windows bad permissions cd} -constraints win -body {
    set d {}
    foreach dd {c:/ d:/ e:/} {
	eval lappend d [glob -nocomplain \
	  -types hidden -dir $dd "System Volume Information"]
    }
    # Old versions of Tcl gave a misleading error that the 
    # directory in question didn't exist.
    if {[llength $d] && [catch {cd [lindex $d 0]} err]} {
	regsub ".*: " $err "" err
	set err
    } else {
        set err "permission denied"
    }
} -cleanup {
    cd $pwd
} -result "permission denied"

cd $pwd
unset d dd pwd

test winFCmd-18.1 {Windows reserved path names} -constraints win -body {
    file pathtype com1
} -result "absolute"

test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body {
    file pathtype com4
} -result "absolute"

test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body {
    file pathtype com9
} -result "absolute"

test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body {
    file pathtype lpt3
} -result "absolute"

test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body {
    file pathtype lpt9
} -result "absolute"

test winFCmd-18.1.6 {Windows reserved path names} -constraints win -body {
    file pathtype nul
} -result "absolute"

test winFCmd-18.1.7 {Windows reserved path names} -constraints win -body {
    file pathtype null
} -result "relative"

test winFCmd-18.2 {Windows reserved path names} -constraints win -body {
    file pathtype com1:
} -result "absolute"

test winFCmd-18.3 {Windows reserved path names} -constraints win -body {
    file pathtype COM1
} -result "absolute"

test winFCmd-18.4 {Windows reserved path names} -constraints win -body {
    file pathtype CoM1:
} -result "absolute"

test winFCmd-18.5 {Windows reserved path names} -constraints win -body {
    file normalize com1:
} -result COM1

test winFCmd-18.6 {Windows reserved path names} -constraints win -body {
    file normalize COM1:
} -result COM1

test winFCmd-18.7 {Windows reserved path names} -constraints win -body {
    file normalize cOm1
} -result COM1

test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
    file normalize cOm1:
} -result COM1


test winFCmd-19.1 {Windows extended path names} -constraints nt -body {
    file normalize //?/c:/windows/win.ini
} -result //?/c:/windows/win.ini

test winFCmd-19.2 {Windows extended path names} -constraints nt -body {
    file normalize //?/c:/windows/../windows/win.ini
} -result //?/c:/windows/win.ini

test winFCmd-19.3 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.4 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.5 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] errormsg ;#$res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 1 errormsg]

test winFCmd-19.6 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]

test winFCmd-19.7 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
    } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {} [list tcl[pid].tmp]]

test winFCmd-19.8 {Windows extended path names} -constraints nt -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f

Changes to tests/winFile.test.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
} {0}
test winFile-1.4 {TclpGetUserHome} {win nt nonPortable} {
    catch {glob ~stanton@workgroup}
} {0}

test winFile-2.1 {TclpMatchFiles: case sensitivity} {win} {
    makeFile {} GlobCapS
    set args [list -nocomplain -tails -directory [temporaryDirectory]]
    set result [list [glob {*}$args GlobC*] [glob {*}$args globc*]]
    removeFile GlobCapS
    set result
} {GlobCapS GlobCapS}
test winFile-2.2 {TclpMatchFiles: case sensitivity} {win} {
    makeFile {} globlower
    set args [list -nocomplain -tails -directory [temporaryDirectory]]
    set result [list [glob {*}$args globl*] [glob {*}$args gLOBl*]]
    removeFile globlower
    set result
} {globlower globlower}

test winFile-3.1 {file system} {win testvolumetype} {
    set res "volume types ok"
    foreach vol [file volumes] {







<
|





<
|







56
57
58
59
60
61
62

63
64
65
66
67
68

69
70
71
72
73
74
75
76
} {0}
test winFile-1.4 {TclpGetUserHome} {win nt nonPortable} {
    catch {glob ~stanton@workgroup}
} {0}

test winFile-2.1 {TclpMatchFiles: case sensitivity} {win} {
    makeFile {} GlobCapS

    set result [list [glob -nocomplain GlobC*] [glob -nocomplain globc*]]
    removeFile GlobCapS
    set result
} {GlobCapS GlobCapS}
test winFile-2.2 {TclpMatchFiles: case sensitivity} {win} {
    makeFile {} globlower

    set result [list [glob -nocomplain globl*] [glob -nocomplain gLOBl*]]
    removeFile globlower
    set result
} {globlower globlower}

test winFile-3.1 {file system} {win testvolumetype} {
    set res "volume types ok"
    foreach vol [file volumes] {

Changes to tests/winPipe.test.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest
namespace import -force ::tcltest::*
unset -nocomplain path


set org_pwd [pwd]
set bindir [file join $org_pwd [file dirname [info nameofexecutable]]]
set cat32 [file join $bindir cat32.exe]

# several test-cases here expect current directory == [temporaryDirectory]:
cd [temporaryDirectory]

testConstraint exec         [llength [info commands exec]]
testConstraint testexcept   [llength [info commands testexcept]]
testConstraint cat32        [file exists $cat32]
testConstraint AllocConsole [catch {puts console1 ""}]
testConstraint RealConsole  [expr {![testConstraint AllocConsole]}]

set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n







<
|


<
<
<







13
14
15
16
17
18
19

20
21
22



23
24
25
26
27
28
29
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest
namespace import -force ::tcltest::*
unset -nocomplain path



set bindir [file join [pwd] [file dirname [info nameofexecutable]]]
set cat32 [file join $bindir cat32.exe]




testConstraint exec         [llength [info commands exec]]
testConstraint testexcept   [llength [info commands testexcept]]
testConstraint cat32        [file exists $cat32]
testConstraint AllocConsole [catch {puts console1 ""}]
testConstraint RealConsole  [expr {![testConstraint AllocConsole]}]

set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
		exec {*}$cmd {*}$args
	    } r]} {
		set r "ERROR: $r"
	    }
	    if {$r ne $e} {
		append broken "\[ERROR\]: exec [file extension [lindex $cmd 0]] on $args\n  -- result:\n$r\n  -- expected:\n$e\n"
	    }
	    if {$single & 8} {
		# if test exe only:
		break
	    }
	}
    }
    return $broken
}

### validate the raw output of BuildCommandLine().
###







<
<
<
<







344
345
346
347
348
349
350




351
352
353
354
355
356
357
		exec {*}$cmd {*}$args
	    } r]} {
		set r "ERROR: $r"
	    }
	    if {$r ne $e} {
		append broken "\[ERROR\]: exec [file extension [lindex $cmd 0]] on $args\n  -- result:\n$r\n  -- expected:\n$e\n"
	    }




	}
    }
    return $broken
}

### validate the raw output of BuildCommandLine().
###
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
	} 20
	lappend lst $args
    } 10
    _testExecArgs 0 {*}$lst
} -result {} -cleanup {
    unset -nocomplain lst args a map maps
}

set injectList {
    "test\"\nwhoami"     "test\"\"\nwhoami"
    "test\"\"\"\nwhoami" "test\"\"\"\"\nwhoami"
    "test;\n&echo \""    "\"test;\n&echo \""
    "test\";\n&echo \""  "\"test\";\n&echo \""
    "\"\"test\";\n&echo \""
}

test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args} \
-constraints {win exec} -body {
    # test exe only, because currently there is no proper way to escape a new-line char resp. 
    # to supply a new-line to the batch-files within arguments (command line is truncated).
    _testExecArgs 8 \
	[list START     {*}$injectList END] \
	[list "START\"" {*}$injectList END] \
	[list START     {*}$injectList "\"END"] \
	[list "START\"" {*}$injectList "\"END"]
} -result {}

test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args (batch)} \
-constraints {win exec knownBug} -body {
    # this will fail if executed batch-file, because currently there is no proper way to escape a new-line char.
    _testExecArgs 0 $injectList
} -result {}


rename _testExecArgs {}

# restore old values for env(TMP) and env(TEMP)

if {[catch {set env(TMP) $env_tmp}]} {
    unset env(TMP)
}
if {[catch {set env(TEMP) $env_temp}]} {
    unset env(TEMP)
}

# cleanup
file delete big little stdout stderr nothing echoArgs.tcl echoArgs.bat 
file delete -force [file join [temporaryDirectory] test(Dir)Check]
::tcltest::cleanupTests
# back to original directory:
cd $org_pwd; unset org_pwd
return







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















<
<

550
551
552
553
554
555
556


























557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572


573
	} 20
	lappend lst $args
    } 10
    _testExecArgs 0 {*}$lst
} -result {} -cleanup {
    unset -nocomplain lst args a map maps
}



























rename _testExecArgs {}

# restore old values for env(TMP) and env(TEMP)

if {[catch {set env(TMP) $env_tmp}]} {
    unset env(TMP)
}
if {[catch {set env(TEMP) $env_temp}]} {
    unset env(TEMP)
}

# cleanup
file delete big little stdout stderr nothing echoArgs.tcl echoArgs.bat 
file delete -force [file join [temporaryDirectory] test(Dir)Check]
::tcltest::cleanupTests


return

Changes to tests/winTime.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint testwinclock [llength [info commands testwinclock]]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

# The next two tests will crash on Windows if the check for negative
# clock values is not done properly.

test winTime-1.1 {TclpGetDate} {win} {
    set ::env(TZ) JST-9
    set result [clock format -1 -format %Y]







<







12
13
14
15
16
17
18

19
20
21
22
23
24
25

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint testwinclock [llength [info commands testwinclock]]


# The next two tests will crash on Windows if the check for negative
# clock values is not done properly.

test winTime-1.1 {TclpGetDate} {win} {
    set ::env(TZ) JST-9
    set result [clock format -1 -format %Y]
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
    set result
} {1969}

# Next test tries to make sure that the Tcl clock stays in step
# with the Windows clock.  30 sec really isn't enough,
# but how much time does a tester have patience for?

test winTime-2.1 {Synchronization of Tcl and Windows clocks} {testwinclock knownMsvcBug} {
    # May fail due to OS/hardware discrepancies.  See:
    # http://support.microsoft.com/default.aspx?scid=kb;en-us;274323
    set failed {}
    set ok 1
    foreach start_sec [testwinclock] break
    while { 1 } {
	foreach { sys_sec sys_usec tcl_sec tcl_usec } [testwinclock] break
	set diff [expr { $tcl_sec - $sys_sec
			 + 1.0e-6 * ( $tcl_usec - $sys_usec ) }]
        if { abs($diff) > 0.1 } {
	    set failed "Tcl clock differs from system clock by $diff sec"
	    break
	} else {
	    testwinsleep 1
	}
	if { $sys_sec - $start_sec >= 30 } break
    }
    set failed
} {}

# cleanup
::tcltest::cleanupTests
return







|









|













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
    set result
} {1969}

# Next test tries to make sure that the Tcl clock stays in step
# with the Windows clock.  30 sec really isn't enough,
# but how much time does a tester have patience for?

test winTime-2.1 {Synchronization of Tcl and Windows clocks} {testwinclock} {
    # May fail due to OS/hardware discrepancies.  See:
    # http://support.microsoft.com/default.aspx?scid=kb;en-us;274323
    set failed {}
    set ok 1
    foreach start_sec [testwinclock] break
    while { 1 } {
	foreach { sys_sec sys_usec tcl_sec tcl_usec } [testwinclock] break
	set diff [expr { $tcl_sec - $sys_sec
			 + 1.0e-6 * ( $tcl_usec - $sys_usec ) }]
        if { abs($diff) > 0.06 } {
	    set failed "Tcl clock differs from system clock by $diff sec"
	    break
	} else {
	    testwinsleep 1
	}
	if { $sys_sec - $start_sec >= 30 } break
    }
    set failed
} {}

# cleanup
::tcltest::cleanupTests
return

Changes to tools/checkLibraryDoc.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# checkLibraryDoc.tcl --
#
# This script attempts to determine what APIs exist in the source base that
# have not been documented.  By grepping through all of the doc/*.3 man
# pages, looking for "Pkg_*" (e.g., Tcl_ or Tk_), and comparing this list
# against the list of Pkg_ APIs found in the source (e.g., tcl8.5/*/*.[ch])
# we create six lists:
#      1) APIs in Source not in Docs.
#      2) APIs in Docs not in Source.
#      3) Internal APIs and structs.
#      4) Misc APIs and structs that we are not documenting.
#      5) Command APIs (e.g., Tcl_ArrayObjCmd.)
#      6) Proc pointers (e.g., Tcl_CloseProc.)
#
# Note: Each list is "a best guess" approximation.  If developers write
# non-standard code, this script will produce erroneous results.  Each
# list should be carefully checked for accuracy.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.


lappend auto_path "c:/program\ files/tclpro1.2/win32-ix86/bin"
#lappend auto_path "/home/surles/cvs/tclx8.0/tcl/unix"


|
|

|







|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# checkLibraryDoc.tcl --
#
# This script attempts to determine what APIs exist in the source base that 
# have not been documented.  By grepping through all of the doc/*.3 man 
# pages, looking for "Pkg_*" (e.g., Tcl_ or Tk_), and comparing this list
# against the list of Pkg_ APIs found in the source (e.g., tcl8.2/*/*.[ch])
# we create six lists:
#      1) APIs in Source not in Docs.
#      2) APIs in Docs not in Source.
#      3) Internal APIs and structs.
#      4) Misc APIs and structs that we are not documenting.
#      5) Command APIs (e.g., Tcl_ArrayObjCmd.)
#      6) Proc pointers (e.g., Tcl_CloseProc.)
# 
# Note: Each list is "a best guess" approximation.  If developers write
# non-standard code, this script will produce erroneous results.  Each
# list should be carefully checked for accuracy. 
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.


lappend auto_path "c:/program\ files/tclpro1.2/win32-ix86/bin"
#lappend auto_path "/home/surles/cvs/tclx8.0/tcl/unix"
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    Tk_SavedOption \
    Tk_SavedOptions \
    Tk_SegType \
    Tk_TextLayout \
    Tk_Window \
}

# Misc junk that appears in the comments of the source.  This just
# allows us to filter comments that "fool" the script.

set CommentList {
    Tcl_Create\[Obj\]Command \
    Tcl_DecrRefCount\\n \
    Tcl_NewObj\\n \
    Tk_GetXXX \
}

# Main entry point to this script.

proc main {} {
    global argv0
    global argv

    set len [llength $argv]
    if {($len != 2) && ($len != 3)} {
	puts "usage: $argv0 pkgName pkgDir \[outFile\]"
	puts "   pkgName == Tcl,Tk"

	exit 1
    }

    set pkg [lindex $argv 0]
    set dir [lindex $argv 1]
    if {[llength $argv] == 3} {
	set file [open [lindex $argv 2] w]
    } else {
	set file stdout
    }

    foreach {c d} [compare [grepCode $dir $pkg] [grepDocs $dir $pkg]] {}
    filter $c $d $dir $pkg $file

    if {$file ne "stdout"} {
	close $file
    }
    return
}

# Intersect the two list and write out the sets of APIs in one
# list that is not in the other.

proc compare {list1 list2} {
    set inter [intersect3 $list1 $list2]
    return [list [lindex $inter 0] [lindex $inter 2]]
}

# Filter the lists into the six lists we report on.  Then write
# the results to the file.

proc filter {code docs dir pkg {outFile stdout}} {
    set apis  {}

    # A list of Tcl command APIs.  These are not documented.
    # This list should just be verified for accuracy.

    set cmds  {}

    # A list of proc pointer structs.  These are not documented.
    # This list should just be verified for accuracy.

    set procs {}

    # A list of internal declarations.  These are not documented.
    # This list should just be verified for accuracy.

    set decls [grepDecl $dir $pkg]

    # A list of misc. procedure declarations that are not documented.
    # This list should just be verified for accuracy.

    set misc [grepMisc $dir $pkg]

    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"

    # A list of APIs in the source, not in the docs.
    # This list should just be verified for accuracy.

    foreach x $code {
	if {[string match *Cmd $x]} {
	    if {[string match ${pkg}* $x]} {
		lappend cmds $x







|












|
|





>














|




|


















|
















|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    Tk_SavedOption \
    Tk_SavedOptions \
    Tk_SegType \
    Tk_TextLayout \
    Tk_Window \
}

# Misc junk that appears in the comments of the source.  This just 
# allows us to filter comments that "fool" the script.

set CommentList {
    Tcl_Create\[Obj\]Command \
    Tcl_DecrRefCount\\n \
    Tcl_NewObj\\n \
    Tk_GetXXX \
}

# Main entry point to this script.

proc main {} {
    global argv0 
    global argv 

    set len [llength $argv]
    if {($len != 2) && ($len != 3)} {
	puts "usage: $argv0 pkgName pkgDir \[outFile\]"
	puts "   pkgName == Tcl,Tk"
	puts "   pkgDir  == /home/surles/cvs/tcl8.2"
	exit 1
    }

    set pkg [lindex $argv 0]
    set dir [lindex $argv 1]
    if {[llength $argv] == 3} {
	set file [open [lindex $argv 2] w]
    } else {
	set file stdout
    }

    foreach {c d} [compare [grepCode $dir $pkg] [grepDocs $dir $pkg]] {}
    filter $c $d $dir $pkg $file

    if {$file != "stdout"} {
	close $file
    }
    return
}
    
# Intersect the two list and write out the sets of APIs in one
# list that is not in the other.

proc compare {list1 list2} {
    set inter [intersect3 $list1 $list2]
    return [list [lindex $inter 0] [lindex $inter 2]]
}

# Filter the lists into the six lists we report on.  Then write
# the results to the file.

proc filter {code docs dir pkg {outFile stdout}} {
    set apis  {}

    # A list of Tcl command APIs.  These are not documented.
    # This list should just be verified for accuracy.

    set cmds  {}
    
    # A list of proc pointer structs.  These are not documented.
    # This list should just be verified for accuracy.

    set procs {}

    # A list of internal declarations.  These are not documented.
    # This list should just be verified for accuracy.

    set decls [grepDecl $dir $pkg]

    # A list of misc. procedure declarations that are not documented.
    # This list should just be verified for accuracy.

    set misc [grepMisc $dir $pkg]

    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"
    
    # A list of APIs in the source, not in the docs.
    # This list should just be verified for accuracy.

    foreach x $code {
	if {[string match *Cmd $x]} {
	    if {[string match ${pkg}* $x]} {
		lappend cmds $x
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    dump $procs "Proc pointers." $outFile
    return
}

# Print the list of APIs if the list is not null.

proc dump {list title file} {
    if {$list ne ""} {
	puts $file ""
	puts $file $title
	puts $file "---------------------------------------------------------"
	foreach x $list {
	    puts $file $x
	}
    }







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
    dump $procs "Proc pointers." $outFile
    return
}

# Print the list of APIs if the list is not null.

proc dump {list title file} {
    if {$list != {}} {
	puts $file ""
	puts $file $title
	puts $file "---------------------------------------------------------"
	foreach x $list {
	    puts $file $x
	}
    }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    return [lsort [array names result]]
}

# Grep into "generic/pkgIntDecls.h" looking for APIs that match $pkg_*.
# (e.g., Tcl_Export).  Return a list of APIs.

proc grepDecl {dir pkg} {
    set file [file join $dir generic "[string tolower $pkg]IntDecls.h"]
    set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_.*" $file]
    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"

    foreach a $apis {
	if {[regexp -- $pat1 $a main n1]} {
	    set result([string trim $n1]) 1
	}
    }
    return [lsort [array names result]]
}

# Grep into "*/*.[ch]" looking for APIs that match $pkg_Db*.
# (e.g., Tcl_DbCkalloc).  Return a list of APIs.

proc grepMisc {dir pkg} {
    global CommentList
    global StructList

    set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_Db.*" "${dir}/\*/\*\.\[ch\]"]
    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"

    foreach a $apis {
	if {[regexp -- $pat1 $a main n1]} {
	    set dbg([string trim $n1]) 1
	}







|

















|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    return [lsort [array names result]]
}

# Grep into "generic/pkgIntDecls.h" looking for APIs that match $pkg_*.
# (e.g., Tcl_Export).  Return a list of APIs.

proc grepDecl {dir pkg} {
    set file [file join $dir generic "[string tolower $pkg]IntDecls.h"] 
    set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_.*" $file]
    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"

    foreach a $apis {
	if {[regexp -- $pat1 $a main n1]} {
	    set result([string trim $n1]) 1
	}
    }
    return [lsort [array names result]]
}

# Grep into "*/*.[ch]" looking for APIs that match $pkg_Db*.
# (e.g., Tcl_DbCkalloc).  Return a list of APIs.

proc grepMisc {dir pkg} {
    global CommentList
    global StructList
    
    set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_Db.*" "${dir}/\*/\*\.\[ch\]"]
    set pat1 ".*(${pkg}_\[A-z0-9]+).*$"

    foreach a $apis {
	if {[regexp -- $pat1 $a main n1]} {
	    set dbg([string trim $n1]) 1
	}

Changes to tools/configure.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run to configure the
dnl	Makefile in this directory.
AC_INIT
AC_CONFIG_SRCDIR([man2tcl.c])
AC_PREREQ([2.59])

# Recover information that Tcl computed with its configure script.

#--------------------------------------------------------------------
#       See if there was a command-line option for where Tcl is;  if
#       not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------



|
<
|







1
2
3
4

5
6
7
8
9
10
11
12
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run to configure the
dnl	Makefile in this directory.
AC_INIT(man2tcl.c)

AC_PREREQ(2.57)

# Recover information that Tcl computed with its configure script.

#--------------------------------------------------------------------
#       See if there was a command-line option for where Tcl is;  if
#       not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------

Changes to tools/encoding/Makefile.

1
2
3
4
5
6
7
8
9
#
# This file is a Makefile to compile all the encoding files.
#
# Run "make" to compile all the encoding files (*.txt,*.esc) into the
# format that Tcl can use (*.enc).  It is your responsibility to move the
# encoding files to the appropriate place ($TCL_ROOT/library/encoding
#
# The .txt files in this directory come from the Unicode CD and are covered
# by the following copyright notice:

|







1
2
3
4
5
6
7
8
9
#
# This file is a Makefile to compile all the encoding files.  
#
# Run "make" to compile all the encoding files (*.txt,*.esc) into the
# format that Tcl can use (*.enc).  It is your responsibility to move the
# encoding files to the appropriate place ($TCL_ROOT/library/encoding
#
# The .txt files in this directory come from the Unicode CD and are covered
# by the following copyright notice:
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
#
# Recipient is granted the right to make copies in any form for
# internal distribution and to freely use the information supplied
# in the creation of products supporting Unicode.  Unicode, Inc.
# specifically excludes the right to re-distribute this file directly
# to third parties or other organizations whether for profit or not.
#
# In other words:  Don't put this file on the Internet.  People who want to
# get it over the Internet should do so directly from ftp://unicode.org.  They
# can therefore be assured of getting the most recent and accurate version.
#
#----------------------------------------------------------------------------
#
# The txt2enc program built by this makefile is used to compile individual
# .txt files into .enc files, the format that Tcl understands for encoding
# files.  This compilation to a different format is allowed by the above
# restriction.
#
# The files shiftjis.txt and jis0208.txt were modified from the original
# ones provided on the Unicode CD.  The double-width backslash character
# 0x815F in these two Japanese encodings was being mapped to Unicode 005C
# (REVERSE SOLIDUS), the normal backslash character.  They have been
# changed to map 0x815F to Unicode FF3C (FULLWIDTH REVERSE SOLIDUS) and let
# the regular backslash character map to itself.  This follows how cp932
# behaves.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: @(#) Makefile 1.1 98/01/28 11:41:36
#

EUC_ENCODINGS = euc-cn.txt euc-kr.txt euc-jp.txt

encodings: clean txt2enc $(EUC_ENCODINGS)
	@echo Compiling encoding files.
	@for p in *.esc; do \
	    base=`echo $$p | sed 's/\..*$$//'`; \
	    echo $$base.enc; \
	    echo "# Encoding file: $$base, escape-driven" > $$base.enc; \
	    echo "E" >> $$base.enc; \
	    cat $$p >> $$base.enc; \
	done
	@for p in *.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -e 0 -u 1 $$p > $$enc; \
	done
	@echo
	@echo Compiling special versions of encoding files.
	@for p in ascii.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -m $$p > $$enc; \
	done
	@for p in jis0208.txt; do \







|






|

|

















|















|







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
#
# Recipient is granted the right to make copies in any form for
# internal distribution and to freely use the information supplied
# in the creation of products supporting Unicode.  Unicode, Inc.
# specifically excludes the right to re-distribute this file directly
# to third parties or other organizations whether for profit or not.
#
# In other words:  Don't put this file on the Internet.  People who want to 
# get it over the Internet should do so directly from ftp://unicode.org.  They
# can therefore be assured of getting the most recent and accurate version.
#
#----------------------------------------------------------------------------
#
# The txt2enc program built by this makefile is used to compile individual
# .txt files into .enc files, the format that Tcl understands for encoding 
# files.  This compilation to a different format is allowed by the above
# restriction. 
#
# The files shiftjis.txt and jis0208.txt were modified from the original
# ones provided on the Unicode CD.  The double-width backslash character
# 0x815F in these two Japanese encodings was being mapped to Unicode 005C
# (REVERSE SOLIDUS), the normal backslash character.  They have been
# changed to map 0x815F to Unicode FF3C (FULLWIDTH REVERSE SOLIDUS) and let
# the regular backslash character map to itself.  This follows how cp932
# behaves.
#
# Copyright (c) 1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: @(#) Makefile 1.1 98/01/28 11:41:36
#

EUC_ENCODINGS = euc-cn.txt euc-kr.txt euc-jp.txt 

encodings: clean txt2enc $(EUC_ENCODINGS)
	@echo Compiling encoding files.
	@for p in *.esc; do \
	    base=`echo $$p | sed 's/\..*$$//'`; \
	    echo $$base.enc; \
	    echo "# Encoding file: $$base, escape-driven" > $$base.enc; \
	    echo "E" >> $$base.enc; \
	    cat $$p >> $$base.enc; \
	done
	@for p in *.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -e 0 -u 1 $$p > $$enc; \
	done
	@echo 
	@echo Compiling special versions of encoding files.
	@for p in ascii.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -m $$p > $$enc; \
	done
	@for p in jis0208.txt; do \

Changes to tools/encoding/big5.txt.

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
# BIG5.TXT
# Date: 2015-12-02 23:52:00 GMT [KW]

# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#









#	Name:             BIG5 to Unicode table (complete)
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#
#	General notes:

#




# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in BIG5 files.


#








# This table contains one set of mappings from BIG5 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of BIG5 and Unicode, consult the
# VENDORS mapping data.
#
#	WARNING!  It is currently impossible to provide round-trip compatibility
#		between BIG5 and Unicode.
#
#	A number of characters are not currently mapped because
#		of conflicts with other mappings.  They are as follows:
#
#       BIG5        Description                    Comments
#
#       0xA15A      SPACING UNDERSCORE             duplicates A1C4
#       0xA1C3      SPACING HEAVY OVERSCORE        not in Unicode
#       0xA1C5      SPACING HEAVY UNDERSCORE       not in Unicode
#       0xA1FE      LT DIAG UP RIGHT TO LOW LEFT   duplicates A2AC
#       0xA240      LT DIAG UP LEFT TO LOW RIGHT   duplicates A2AD
#       0xA2CC      HANGZHOU NUMERAL TEN           conflicts with A451 mapping
#       0xA2CE      HANGZHOU NUMERAL THIRTY        conflicts with A4CA mapping
#
#	We currently map all of these characters to U+FFFD REPLACEMENT CHARACTER.
#		It is also possible to map these characters to their duplicates, or to
#		the user zone.
#
#	Notes:
#
#	1. In addition to the above, there is some uncertainty about the
#       mappings in the range C6A1 - C8FE, and F9DD - F9FE.  The ETEN
#	version of BIG5 organizes the former range differently, and adds
#	additional characters in the latter range.  The correct mappings
#	these ranges need to be determined.
#
#	2.  There is an uncertainty in the mapping of the Big Five character
#	0xA3BC.  This character occurs within the Big Five block of tone marks
#	for bopomofo and is intended to be the tone mark for the first tone in
#	Mandarin Chinese.  We have selected the mapping U+02C9 MODIFIER LETTER
#	MACRON (Mandarin Chinese first tone) to reflect this semantic.
#	However, because bopomofo uses the absense of a tone mark to indicate
#	the first Mandarin tone, most implementations of Big Five represent
#	this character with a blank space, and so a mapping such as U+2003 EM
#	SPACE might be preferred.


#
#	Format:  Three tab-separated columns
#		 Column #1 is the BIG5 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3  is the Unicode name (follows a comment sign, '#')
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in BIG5 order
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.0d3, 11 February 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
|
<
>
|
<

>
>
>
>
>
>
>
>
>


|

|
>
>

<
>

>
>
>
>
|
<
>
>

>
>
>
>
>
>
>
>
|
<
<
<
|
<


|
















|
|




|
|
|


|
|
|
|
|
|
|
|
>
>





|
|
|
|
|
|
|



|

<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
# big5.txt --

#
#	BIG5 to Unicode table (modified)

#
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in BIG5 files.
#
#
#	Name:             BIG5 to Unicode table (complete)
#	Unicode version:  1.1
#	Table version:    0.0d3
#	Table format:     Format A
#	Date:             11 February 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#

#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole

#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data Metis and Taligent currently have on how



#       BIG5 characters map into Unicode.

#
#	WARNING!  It is currently impossible to provide round-trip compatibility
#		between BIG5 and Unicode.  
#
#	A number of characters are not currently mapped because
#		of conflicts with other mappings.  They are as follows:
#
#       BIG5        Description                    Comments
#
#       0xA15A      SPACING UNDERSCORE             duplicates A1C4
#       0xA1C3      SPACING HEAVY OVERSCORE        not in Unicode
#       0xA1C5      SPACING HEAVY UNDERSCORE       not in Unicode
#       0xA1FE      LT DIAG UP RIGHT TO LOW LEFT   duplicates A2AC
#       0xA240      LT DIAG UP LEFT TO LOW RIGHT   duplicates A2AD
#       0xA2CC      HANGZHOU NUMERAL TEN           conflicts with A451 mapping
#       0xA2CE      HANGZHOU NUMERAL THIRTY        conflicts with A4CA mapping
#
#	We currently map all of these characters to U+FFFD REPLACEMENT CHARACTER.
#		It is also possible to map these characters to their duplicates, or to
#		the user zone.  
#	
#	Notes:
#
#	1. In addition to the above, there is some uncertainty about the
#       mappings in the range C6A1 - C8FE, and F9DD - F9FE.  The ETEN
#		version of BIG5 organizes the former range differently, and adds
#		additional characters in the latter range.  The correct mappings
#		these ranges need to be determined.
#
#	2.  There is an uncertainty in the mapping of the Big Five character
#		0xA3BC.  This character occurs within the Big Five block of tone marks
#		for bopomofo and is intended to be the tone mark for the first tone in
#		Mandarin Chinese.  We have selected the mapping U+02C9 MODIFIER LETTER
#		MACRON (Mandarin Chinese first tone) to reflect this semantic.  
#		However, because bopomofo uses the absense of a tone mark to indicate
#		the first Mandarin tone, most implementations of Big Five represent
#		this character with a blank space, and so a mapping such as U+2003 EM SPACE
#		might be preferred.  
#		
#			
#
#	Format:  Three tab-separated columns
#		 Column #1 is the BIG5 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3  is the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#
#	The entries are in BIG5 order
#
#	Any comments or problems, contact <John_Jenki[email protected]>
#














#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Deleted tools/encoding/cns11643.txt.

more than 10,000 changes

Changes to tools/encoding/cp1250.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1250 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1250 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1250 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1250 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1251.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1251 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1251 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1251 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1251 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1252.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1252 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1252 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1252 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1252 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1253.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1253 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1253 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1253 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1253 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1254.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1254 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1254 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1254 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1254 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1255.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1255 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1255 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1255 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1255 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1256.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1256 to Unicode table
#    Unicode version: 2.1
#    Table version: 2.01
#    Table format:  Format A
#    Date:          01/5/99
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1256 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1256 to Unicode table
#    Unicode version: 2.1
#    Table version: 2.01
#    Table format:  Format A
#    Date:          01/5/99
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1256 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1257.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1257 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1257 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1257 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1257 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1258.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1258 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1258 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp1258 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1258 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp874.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp874 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          02/28/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp874 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp874 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          02/28/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp874 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp932.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp932 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp932 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp932 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp932 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp936.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp936 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp936 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp936 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp936 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp949.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp949 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp949 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp949 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp949 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp950.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp950 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       Shawn.Steel[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp950 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
#    Name:     cp950 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp950 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/gb2312.txt.

1
2
3
4
5
6
7
8
9
10
11
12
# gb2312.txt --
#
#	GB2312 to Unicode table (modified)
#
# Copyright (c) 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in GB2312 files.
#




|







1
2
3
4
5
6
7
8
9
10
11
12
# gb2312.txt --
#
#	GB2312 to Unicode table (modified)
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in GB2312 files.
#

Changes to tools/encoding/iso8859-1.txt.

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
# 8859-1.TXT
# Date: 2015-12-02 20:19:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-1:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-1:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-1 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-1:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-1:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-1 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-10.txt.

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
# 8859-10.TXT
# Date: 2015-12-02 21:53:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-10:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 October 11 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-10:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-10 order.
#
#	Version history
#	1.0 version new.
#   1.1 corrected mistake in mapping of 0xA4
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















|
<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-10:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table format:     Format A
#	Date:             1999 October 11
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-10:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-10 order.
#
#	Version history
#	1.0 version new.
#       1.1 corrected mistake in mapping of 0xA4


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Deleted tools/encoding/iso8859-11.txt.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# 8859-11.TXT
# Date: 2015-12-02 21:55:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-11:2001 to Unicode
#	Unicode version:  3.2
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2002 October 7 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <[email protected]>
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-11:2001 characters map into Unicode.
#
#	ISO/IEC 8859-11:2001 is equivalent to TIS 620-2533 (1990) with
#	the addition of 0xA0 NO-BREAK SPACE.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-11 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-11 order.
#
#	Version history:
#		2002 October 7  Created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
0x06	0x0006	#	ACKNOWLEDGE
0x07	0x0007	#	BELL
0x08	0x0008	#	BACKSPACE
0x09	0x0009	#	HORIZONTAL TABULATION
0x0A	0x000A	#	LINE FEED
0x0B	0x000B	#	VERTICAL TABULATION
0x0C	0x000C	#	FORM FEED
0x0D	0x000D	#	CARRIAGE RETURN
0x0E	0x000E	#	SHIFT OUT
0x0F	0x000F	#	SHIFT IN
0x10	0x0010	#	DATA LINK ESCAPE
0x11	0x0011	#	DEVICE CONTROL ONE
0x12	0x0012	#	DEVICE CONTROL TWO
0x13	0x0013	#	DEVICE CONTROL THREE
0x14	0x0014	#	DEVICE CONTROL FOUR
0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
0x16	0x0016	#	SYNCHRONOUS IDLE
0x17	0x0017	#	END OF TRANSMISSION BLOCK
0x18	0x0018	#	CANCEL
0x19	0x0019	#	END OF MEDIUM
0x1A	0x001A	#	SUBSTITUTE
0x1B	0x001B	#	ESCAPE
0x1C	0x001C	#	FILE SEPARATOR
0x1D	0x001D	#	GROUP SEPARATOR
0x1E	0x001E	#	RECORD SEPARATOR
0x1F	0x001F	#	UNIT SEPARATOR
0x20	0x0020	#	SPACE
0x21	0x0021	#	EXCLAMATION MARK
0x22	0x0022	#	QUOTATION MARK
0x23	0x0023	#	NUMBER SIGN
0x24	0x0024	#	DOLLAR SIGN
0x25	0x0025	#	PERCENT SIGN
0x26	0x0026	#	AMPERSAND
0x27	0x0027	#	APOSTROPHE
0x28	0x0028	#	LEFT PARENTHESIS
0x29	0x0029	#	RIGHT PARENTHESIS
0x2A	0x002A	#	ASTERISK
0x2B	0x002B	#	PLUS SIGN
0x2C	0x002C	#	COMMA
0x2D	0x002D	#	HYPHEN-MINUS
0x2E	0x002E	#	FULL STOP
0x2F	0x002F	#	SOLIDUS
0x30	0x0030	#	DIGIT ZERO
0x31	0x0031	#	DIGIT ONE
0x32	0x0032	#	DIGIT TWO
0x33	0x0033	#	DIGIT THREE
0x34	0x0034	#	DIGIT FOUR
0x35	0x0035	#	DIGIT FIVE
0x36	0x0036	#	DIGIT SIX
0x37	0x0037	#	DIGIT SEVEN
0x38	0x0038	#	DIGIT EIGHT
0x39	0x0039	#	DIGIT NINE
0x3A	0x003A	#	COLON
0x3B	0x003B	#	SEMICOLON
0x3C	0x003C	#	LESS-THAN SIGN
0x3D	0x003D	#	EQUALS SIGN
0x3E	0x003E	#	GREATER-THAN SIGN
0x3F	0x003F	#	QUESTION MARK
0x40	0x0040	#	COMMERCIAL AT
0x41	0x0041	#	LATIN CAPITAL LETTER A
0x42	0x0042	#	LATIN CAPITAL LETTER B
0x43	0x0043	#	LATIN CAPITAL LETTER C
0x44	0x0044	#	LATIN CAPITAL LETTER D
0x45	0x0045	#	LATIN CAPITAL LETTER E
0x46	0x0046	#	LATIN CAPITAL LETTER F
0x47	0x0047	#	LATIN CAPITAL LETTER G
0x48	0x0048	#	LATIN CAPITAL LETTER H
0x49	0x0049	#	LATIN CAPITAL LETTER I
0x4A	0x004A	#	LATIN CAPITAL LETTER J
0x4B	0x004B	#	LATIN CAPITAL LETTER K
0x4C	0x004C	#	LATIN CAPITAL LETTER L
0x4D	0x004D	#	LATIN CAPITAL LETTER M
0x4E	0x004E	#	LATIN CAPITAL LETTER N
0x4F	0x004F	#	LATIN CAPITAL LETTER O
0x50	0x0050	#	LATIN CAPITAL LETTER P
0x51	0x0051	#	LATIN CAPITAL LETTER Q
0x52	0x0052	#	LATIN CAPITAL LETTER R
0x53	0x0053	#	LATIN CAPITAL LETTER S
0x54	0x0054	#	LATIN CAPITAL LETTER T
0x55	0x0055	#	LATIN CAPITAL LETTER U
0x56	0x0056	#	LATIN CAPITAL LETTER V
0x57	0x0057	#	LATIN CAPITAL LETTER W
0x58	0x0058	#	LATIN CAPITAL LETTER X
0x59	0x0059	#	LATIN CAPITAL LETTER Y
0x5A	0x005A	#	LATIN CAPITAL LETTER Z
0x5B	0x005B	#	LEFT SQUARE BRACKET
0x5C	0x005C	#	REVERSE SOLIDUS
0x5D	0x005D	#	RIGHT SQUARE BRACKET
0x5E	0x005E	#	CIRCUMFLEX ACCENT
0x5F	0x005F	#	LOW LINE
0x60	0x0060	#	GRAVE ACCENT
0x61	0x0061	#	LATIN SMALL LETTER A
0x62	0x0062	#	LATIN SMALL LETTER B
0x63	0x0063	#	LATIN SMALL LETTER C
0x64	0x0064	#	LATIN SMALL LETTER D
0x65	0x0065	#	LATIN SMALL LETTER E
0x66	0x0066	#	LATIN SMALL LETTER F
0x67	0x0067	#	LATIN SMALL LETTER G
0x68	0x0068	#	LATIN SMALL LETTER H
0x69	0x0069	#	LATIN SMALL LETTER I
0x6A	0x006A	#	LATIN SMALL LETTER J
0x6B	0x006B	#	LATIN SMALL LETTER K
0x6C	0x006C	#	LATIN SMALL LETTER L
0x6D	0x006D	#	LATIN SMALL LETTER M
0x6E	0x006E	#	LATIN SMALL LETTER N
0x6F	0x006F	#	LATIN SMALL LETTER O
0x70	0x0070	#	LATIN SMALL LETTER P
0x71	0x0071	#	LATIN SMALL LETTER Q
0x72	0x0072	#	LATIN SMALL LETTER R
0x73	0x0073	#	LATIN SMALL LETTER S
0x74	0x0074	#	LATIN SMALL LETTER T
0x75	0x0075	#	LATIN SMALL LETTER U
0x76	0x0076	#	LATIN SMALL LETTER V
0x77	0x0077	#	LATIN SMALL LETTER W
0x78	0x0078	#	LATIN SMALL LETTER X
0x79	0x0079	#	LATIN SMALL LETTER Y
0x7A	0x007A	#	LATIN SMALL LETTER Z
0x7B	0x007B	#	LEFT CURLY BRACKET
0x7C	0x007C	#	VERTICAL LINE
0x7D	0x007D	#	RIGHT CURLY BRACKET
0x7E	0x007E	#	TILDE
0x7F	0x007F	#	DELETE
0x80	0x0080	#	<control>
0x81	0x0081	#	<control>
0x82	0x0082	#	<control>
0x83	0x0083	#	<control>
0x84	0x0084	#	<control>
0x85	0x0085	#	<control>
0x86	0x0086	#	<control>
0x87	0x0087	#	<control>
0x88	0x0088	#	<control>
0x89	0x0089	#	<control>
0x8A	0x008A	#	<control>
0x8B	0x008B	#	<control>
0x8C	0x008C	#	<control>
0x8D	0x008D	#	<control>
0x8E	0x008E	#	<control>
0x8F	0x008F	#	<control>
0x90	0x0090	#	<control>
0x91	0x0091	#	<control>
0x92	0x0092	#	<control>
0x93	0x0093	#	<control>
0x94	0x0094	#	<control>
0x95	0x0095	#	<control>
0x96	0x0096	#	<control>
0x97	0x0097	#	<control>
0x98	0x0098	#	<control>
0x99	0x0099	#	<control>
0x9A	0x009A	#	<control>
0x9B	0x009B	#	<control>
0x9C	0x009C	#	<control>
0x9D	0x009D	#	<control>
0x9E	0x009E	#	<control>
0x9F	0x009F	#	<control>
0xA0	0x00A0	#	NO-BREAK SPACE
0xA1	0x0E01	#	THAI CHARACTER KO KAI
0xA2	0x0E02	#	THAI CHARACTER KHO KHAI
0xA3	0x0E03	#	THAI CHARACTER KHO KHUAT
0xA4	0x0E04	#	THAI CHARACTER KHO KHWAI
0xA5	0x0E05	#	THAI CHARACTER KHO KHON
0xA6	0x0E06	#	THAI CHARACTER KHO RAKHANG
0xA7	0x0E07	#	THAI CHARACTER NGO NGU
0xA8	0x0E08	#	THAI CHARACTER CHO CHAN
0xA9	0x0E09	#	THAI CHARACTER CHO CHING
0xAA	0x0E0A	#	THAI CHARACTER CHO CHANG
0xAB	0x0E0B	#	THAI CHARACTER SO SO
0xAC	0x0E0C	#	THAI CHARACTER CHO CHOE
0xAD	0x0E0D	#	THAI CHARACTER YO YING
0xAE	0x0E0E	#	THAI CHARACTER DO CHADA
0xAF	0x0E0F	#	THAI CHARACTER TO PATAK
0xB0	0x0E10	#	THAI CHARACTER THO THAN
0xB1	0x0E11	#	THAI CHARACTER THO NANGMONTHO
0xB2	0x0E12	#	THAI CHARACTER THO PHUTHAO
0xB3	0x0E13	#	THAI CHARACTER NO NEN
0xB4	0x0E14	#	THAI CHARACTER DO DEK
0xB5	0x0E15	#	THAI CHARACTER TO TAO
0xB6	0x0E16	#	THAI CHARACTER THO THUNG
0xB7	0x0E17	#	THAI CHARACTER THO THAHAN
0xB8	0x0E18	#	THAI CHARACTER THO THONG
0xB9	0x0E19	#	THAI CHARACTER NO NU
0xBA	0x0E1A	#	THAI CHARACTER BO BAIMAI
0xBB	0x0E1B	#	THAI CHARACTER PO PLA
0xBC	0x0E1C	#	THAI CHARACTER PHO PHUNG
0xBD	0x0E1D	#	THAI CHARACTER FO FA
0xBE	0x0E1E	#	THAI CHARACTER PHO PHAN
0xBF	0x0E1F	#	THAI CHARACTER FO FAN
0xC0	0x0E20	#	THAI CHARACTER PHO SAMPHAO
0xC1	0x0E21	#	THAI CHARACTER MO MA
0xC2	0x0E22	#	THAI CHARACTER YO YAK
0xC3	0x0E23	#	THAI CHARACTER RO RUA
0xC4	0x0E24	#	THAI CHARACTER RU
0xC5	0x0E25	#	THAI CHARACTER LO LING
0xC6	0x0E26	#	THAI CHARACTER LU
0xC7	0x0E27	#	THAI CHARACTER WO WAEN
0xC8	0x0E28	#	THAI CHARACTER SO SALA
0xC9	0x0E29	#	THAI CHARACTER SO RUSI
0xCA	0x0E2A	#	THAI CHARACTER SO SUA
0xCB	0x0E2B	#	THAI CHARACTER HO HIP
0xCC	0x0E2C	#	THAI CHARACTER LO CHULA
0xCD	0x0E2D	#	THAI CHARACTER O ANG
0xCE	0x0E2E	#	THAI CHARACTER HO NOKHUK
0xCF	0x0E2F	#	THAI CHARACTER PAIYANNOI
0xD0	0x0E30	#	THAI CHARACTER SARA A
0xD1	0x0E31	#	THAI CHARACTER MAI HAN-AKAT
0xD2	0x0E32	#	THAI CHARACTER SARA AA
0xD3	0x0E33	#	THAI CHARACTER SARA AM
0xD4	0x0E34	#	THAI CHARACTER SARA I
0xD5	0x0E35	#	THAI CHARACTER SARA II
0xD6	0x0E36	#	THAI CHARACTER SARA UE
0xD7	0x0E37	#	THAI CHARACTER SARA UEE
0xD8	0x0E38	#	THAI CHARACTER SARA U
0xD9	0x0E39	#	THAI CHARACTER SARA UU
0xDA	0x0E3A	#	THAI CHARACTER PHINTHU
0xDF	0x0E3F	#	THAI CURRENCY SYMBOL BAHT
0xE0	0x0E40	#	THAI CHARACTER SARA E
0xE1	0x0E41	#	THAI CHARACTER SARA AE
0xE2	0x0E42	#	THAI CHARACTER SARA O
0xE3	0x0E43	#	THAI CHARACTER SARA AI MAIMUAN
0xE4	0x0E44	#	THAI CHARACTER SARA AI MAIMALAI
0xE5	0x0E45	#	THAI CHARACTER LAKKHANGYAO
0xE6	0x0E46	#	THAI CHARACTER MAIYAMOK
0xE7	0x0E47	#	THAI CHARACTER MAITAIKHU
0xE8	0x0E48	#	THAI CHARACTER MAI EK
0xE9	0x0E49	#	THAI CHARACTER MAI THO
0xEA	0x0E4A	#	THAI CHARACTER MAI TRI
0xEB	0x0E4B	#	THAI CHARACTER MAI CHATTAWA
0xEC	0x0E4C	#	THAI CHARACTER THANTHAKHAT
0xED	0x0E4D	#	THAI CHARACTER NIKHAHIT
0xEE	0x0E4E	#	THAI CHARACTER YAMAKKAN
0xEF	0x0E4F	#	THAI CHARACTER FONGMAN
0xF0	0x0E50	#	THAI DIGIT ZERO
0xF1	0x0E51	#	THAI DIGIT ONE
0xF2	0x0E52	#	THAI DIGIT TWO
0xF3	0x0E53	#	THAI DIGIT THREE
0xF4	0x0E54	#	THAI DIGIT FOUR
0xF5	0x0E55	#	THAI DIGIT FIVE
0xF6	0x0E56	#	THAI DIGIT SIX
0xF7	0x0E57	#	THAI DIGIT SEVEN
0xF8	0x0E58	#	THAI DIGIT EIGHT
0xF9	0x0E59	#	THAI DIGIT NINE
0xFA	0x0E5A	#	THAI CHARACTER ANGKHANKHU
0xFB	0x0E5B	#	THAI CHARACTER KHOMUT
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































































Changes to tools/encoding/iso8859-13.txt.

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
# 8859-13.TXT
# Date: 2015-12-02 22:03:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-13:1998  to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-13:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-13 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













<
<
<
<
<

|

|
|
>











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




#
#	Name:             ISO/IEC 8859-13:1998  to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-13:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-13 order.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-14.txt.

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
# 8859-14.TXT
# Date: 2015-12-02 22:05:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-14:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-14:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-14 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













<
<
<
<
<

|

|
|
>











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




#
#	Name:             ISO/IEC 8859-14:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-14:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-14 order.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
286
287
288
289
290
291
292

0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x0177	#	LATIN SMALL LETTER Y WITH CIRCUMFLEX
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS








>
294
295
296
297
298
299
300
301
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x0177	#	LATIN SMALL LETTER Y WITH CIRCUMFLEX
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS

Changes to tools/encoding/iso8859-15.txt.

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
# 8859-15.TXT
# Date: 2015-12-02 22:06:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-15:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-15:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-15 order.
#
#	Version history
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















<
<
<
<
<

|

|
|
>











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




#
#	Name:             ISO/IEC 8859-15:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-15:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-15 order.
#
#	Version history
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
288
289
290
291
292
293
294

0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x00FE	#	LATIN SMALL LETTER THORN
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS








>
296
297
298
299
300
301
302
303
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x00FE	#	LATIN SMALL LETTER THORN
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS

Changes to tools/encoding/iso8859-16.txt.

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
# 8859-16.TXT
# Date: 2015-12-02 22:08:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-16:2001 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2001 July 26 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#
#	Copyright (c) 1999-2001 Unicode, Inc.  All Rights reserved.














#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-16:2001 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-16 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>













<
<
<
<
<

|

|
|
>











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




#
#	Name:             ISO/IEC 8859-16:2001 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             2001 July 26
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#
#	Copyright (c) 1999-2001 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-16:2001 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-16 order.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-2.txt.

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
# 8859-2.TXT
# Date: 2015-12-02 21:34:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-2:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-2:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-2 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
<
<


|

|
|
>











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




#
#	Name:             ISO 8859-2:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-2:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-2 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-3.txt.

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
# 8859-3.TXT
# Date: 2015-12-02 21:39:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-3:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-3:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-3 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-3:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-3:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-3 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-4.txt.

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
# 8859-4.TXT
# Date: 2015-12-02 21:41:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-4:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-4:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-4 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-4:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-4:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-4 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-5.txt.

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
# 8859-5.TXT
# Date: 2015-12-02 21:43:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-5:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-5:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-5 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
<
<


|

|
|
>











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




#
#	Name:             ISO 8859-5:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-5:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-5 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-6.txt.

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
# 8859-6.TXT
# Date: 2015-12-02 21:44:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-6:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-6:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-6 order.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#       0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
#       of the Arabic digits (U+0660..U+0669).
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
|
|
|
<
<


|

|
|
>











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




#
#	Name:             ISO 8859-6:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-6:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-6 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#	0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
#	of the Arabic digits (U+0660..U+0669).


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-7.txt.

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
# 8859-7.TXT
# Date: 2015-12-02 21:47:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-7:2003 to Unicode
#	Unicode version:  4.0
#	Table version:    3.0
#	Table format:     Format A
#	Date:             2003-Nov-12 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO 8859-7:2003 characters map into Unicode.
#
#	ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
#	and ECMA 118. ISO 8859-7:2003 adds two currency signs
#	and one other character not in the earlier standard.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO 8859-7 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO 8859-7 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#	Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7
#	Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7
#
#	2.0 version updates 1.0 version by adding mappings for the
#	three newly added characters 0xA4, 0xA5, 0xAA.
#
#   3.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<

|
|
|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|


|
<














<
<
<
<
<
<

|

|
|
>











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




#
#	Name:             ISO 8859-7:1987 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO 8859-7:1987 characters map into Unicode.
#
#	ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
#	and ECMA 118.

#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO 8859-7 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO 8859-7 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#	Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7
#	Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7
#






#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
0x9D	0x009D	#	<control>
0x9E	0x009E	#	<control>
0x9F	0x009F	#	<control>
0xA0	0x00A0	#	NO-BREAK SPACE
0xA1	0x2018	#	LEFT SINGLE QUOTATION MARK
0xA2	0x2019	#	RIGHT SINGLE QUOTATION MARK
0xA3	0x00A3	#	POUND SIGN
0xA4	0x20AC	#	EURO SIGN
0xA5	0x20AF	#	DRACHMA SIGN
0xA6	0x00A6	#	BROKEN BAR
0xA7	0x00A7	#	SECTION SIGN
0xA8	0x00A8	#	DIAERESIS
0xA9	0x00A9	#	COPYRIGHT SIGN
0xAA	0x037A	#	GREEK YPOGEGRAMMENI
0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xAC	0x00AC	#	NOT SIGN
0xAD	0x00AD	#	SOFT HYPHEN
0xAF	0x2015	#	HORIZONTAL BAR
0xB0	0x00B0	#	DEGREE SIGN
0xB1	0x00B1	#	PLUS-MINUS SIGN
0xB2	0x00B2	#	SUPERSCRIPT TWO







<
<




<







210
211
212
213
214
215
216


217
218
219
220

221
222
223
224
225
226
227
0x9D	0x009D	#	<control>
0x9E	0x009E	#	<control>
0x9F	0x009F	#	<control>
0xA0	0x00A0	#	NO-BREAK SPACE
0xA1	0x2018	#	LEFT SINGLE QUOTATION MARK
0xA2	0x2019	#	RIGHT SINGLE QUOTATION MARK
0xA3	0x00A3	#	POUND SIGN


0xA6	0x00A6	#	BROKEN BAR
0xA7	0x00A7	#	SECTION SIGN
0xA8	0x00A8	#	DIAERESIS
0xA9	0x00A9	#	COPYRIGHT SIGN

0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xAC	0x00AC	#	NOT SIGN
0xAD	0x00AD	#	SOFT HYPHEN
0xAF	0x2015	#	HORIZONTAL BAR
0xB0	0x00B0	#	DEGREE SIGN
0xB1	0x00B1	#	PLUS-MINUS SIGN
0xB2	0x00B2	#	SUPERSCRIPT TWO

Changes to tools/encoding/iso8859-8.txt.

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
# 8859-8.TXT
# Date: 2015-12-02 21:50:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-8:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2000-Jan-03 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-8:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-8 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.1 version updates to the published 8859-8:1999, correcting
#          the mapping of 0xAF and adding mappings for LRM and RLM.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|

<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-8:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table format:     Format A
#	Date:             2000-Jan-03
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-8:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-8 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#       1.1 version updates to the published 8859-8:1999, correcting
#          the mapping of 0xAF and adding mappings for LRM and RLM.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
252
253
254
255
256
257
258

0xF6	0x05E6	#	HEBREW LETTER TSADI
0xF7	0x05E7	#	HEBREW LETTER QOF
0xF8	0x05E8	#	HEBREW LETTER RESH
0xF9	0x05E9	#	HEBREW LETTER SHIN
0xFA	0x05EA	#	HEBREW LETTER TAV
0xFD	0x200E	#	LEFT-TO-RIGHT MARK
0xFE	0x200F	#	RIGHT-TO-LEFT MARK








>
263
264
265
266
267
268
269
270
0xF6	0x05E6	#	HEBREW LETTER TSADI
0xF7	0x05E7	#	HEBREW LETTER QOF
0xF8	0x05E8	#	HEBREW LETTER RESH
0xF9	0x05E9	#	HEBREW LETTER SHIN
0xFA	0x05EA	#	HEBREW LETTER TAV
0xFD	0x200E	#	LEFT-TO-RIGHT MARK
0xFE	0x200F	#	RIGHT-TO-LEFT MARK

Changes to tools/encoding/iso8859-9.txt.

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
# 8859-9.TXT
# Date: 2015-12-02 21:51:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-9:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
















#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-9:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-9 order.
#
#	ISO/IEC 8859-9 is also equivalent to ISO-IR-148.
#
#	Version history
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html

#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
<
<
<
<



|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|
|
<
<


|

|
|
>











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




#
#	Name:             ISO/IEC 8859-9:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-9:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-9 order.
#
#	ISO/IEC 8859-9 is also equivalent to ISO-IR-148.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
288
289
290
291
292
293
294
295

0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x0131	#	LATIN SMALL LETTER DOTLESS I
0xFE	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS










>
299
300
301
302
303
304
305
306
307
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x0131	#	LATIN SMALL LETTER DOTLESS I
0xFE	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS


Changes to tools/encoding/jis0201.txt.

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
# JIS0201.TXT
# Date: 2015-12-02 23:49:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0201 (1976) to Unicode 1.1 Table
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#
#	General notes:

#







#
# This table contains one set of mappings from JIS X 0201 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited

# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0201 and Unicode, consult the
# VENDORS mapping data.


#





#
#	Format:  Three tab-separated columns
#		Column #1 is the shift JIS code (in hex as 0xXX)
#		Column #2 is the Unicode (in hex as 0xXXXX)
#		Column #3 the Unicode (ISO 10646) name (follows a comment sign)
#
#	The entries are in JIS order
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.

#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
<
<
<
<



|

|
>
>

<
>

>
>
>
>
>
>
>

<
<
<
>
|
|
<
>
>

>
>
>
>
>








|
<
<
<
|

<
<
<
<
>

<
<
<
<
<











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




#
#	Name:             JIS X 0201 (1976) to Unicode 1.1 Table
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#

#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#



#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.

#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#	single-byte JIS X 0201 characters map into Unicode 1.1
#	(ISO/IEC 10646:1-1993 UCS-2).
#
#	Format:  Three tab-separated columns
#		Column #1 is the shift JIS code (in hex as 0xXX)
#		Column #2 is the Unicode (in hex as 0xXXXX)
#		Column #3 the Unicode (ISO 10646) name (follows a comment sign)
#
#	The entries are in JIS order
#
#   These mappings are provisional, pending definition of



#       official mappings by Japanese standards bodies.
#




#	Any comments or problems, contact <[email protected]>
#





#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Changes to tools/encoding/jis0208.txt.

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
# JIS0208.TXT
# Date: 2015-12-02 23:50:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0208 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#
#	General notes:

#







#
# This table contains one set of mappings from JIS X 0208 (1990) into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited

# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0208 (1990) and Unicode, consult the
# VENDORS mapping data.


#




#
#	Format:  Four tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the JIS X 0208 code (in hex as 0xXXXX)
#		 Column #3 is the Unicode (in hex as 0xXXXX)
#		 Column #4 the Unicode name (follows a comment sign, '#')
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0208 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0208 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x7426 -> 0x5406 -> 8406
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.

#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x8140	0x2121	0x3000	# IDEOGRAPHIC SPACE
0x8141	0x2122	0x3001	# IDEOGRAPHIC COMMA
0x8142	0x2123	0x3002	# IDEOGRAPHIC FULL STOP
0x8143	0x2124	0xFF0C	# FULLWIDTH COMMA
0x8144	0x2125	0xFF0E	# FULLWIDTH FULL STOP
0x8145	0x2126	0x30FB	# KATAKANA MIDDLE DOT
<
<
<
<



|

|
>
>

<
>

>
>
>
>
>
>
>

<
<
<
>
|
|
<
>
>

>
>
>
>






|
|
|
|
|
|
|












<
<
<
<
|
<
|
<
<
|

<
<
>

<
<











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




#
#	Name:             JIS X 0208 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#

#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#



#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.

#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       JIS X 0208 (1983) characters map into Unicode.
#
#	Format:  Four tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the JIS X 0208 code (in hex as 0xXXXX)
#		 Column #3 is the Unicode (in hex as 0xXXXX)
#		 Column #4 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0208 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0208 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x7426 -> 0x5406 -> 8406
#




#   The kanji mappings are a normative part of ISO/IEC 10646.  The

#       non-kanji mappings are provisional, pending definition of


#       official mappings by Japanese standards bodies
#


#	Any comments or problems, contact <[email protected]>
#


#
0x8140	0x2121	0x3000	# IDEOGRAPHIC SPACE
0x8141	0x2122	0x3001	# IDEOGRAPHIC COMMA
0x8142	0x2123	0x3002	# IDEOGRAPHIC FULL STOP
0x8143	0x2124	0xFF0C	# FULLWIDTH COMMA
0x8144	0x2125	0xFF0E	# FULLWIDTH FULL STOP
0x8145	0x2126	0x30FB	# KATAKANA MIDDLE DOT

Changes to tools/encoding/jis0212.txt.

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
# JIS0212.TXT
# Date: 2015-12-02 23:51:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0212 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#
#	General notes:

#







#
# This table contains one set of mappings from JIS X 0212 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited

# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0212 and Unicode, consult the
# VENDORS mapping data.


#




#
#	Format:  Three tab-separated columns
#		 Column #1 is the JIS X 0212 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0212 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0212 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x6D63 -> 0x4D43 -> 7767
#






#	Notes:
#
#	1. JIS X 0212 apparently unified the following two symbols
#	   into a single character at 0x2922:
#
#	   LATIN CAPITAL LETTER D WITH STROKE
#	   LATIN CAPITAL LETTER ETH
#
#	   However, JIS X 0212 maintains the distinction between
#	   the lowercase forms of these two elements at 0x2942 and 0x2943.
#	   Given the structre of these JIS encodings, it is clear that
#	   0x2922 and 0x2942 are intended to be a capital/small pair.
#	   Consequently, in the Unicode mapping, 0x2922 is treated as
#	   LATIN CAPITAL LETTER D WITH STROKE.
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x222F	0x02D8	# BREVE
0x2230	0x02C7	# CARON (Mandarin Chinese third tone)
0x2231	0x00B8	# CEDILLA
0x2232	0x02D9	# DOT ABOVE (Mandarin Chinese light tone)
0x2233	0x02DD	# DOUBLE ACUTE ACCENT
0x2234	0x00AF	# MACRON
0x2235	0x02DB	# OGONEK
<
<
<
<



|

|
>
>

<
>

>
>
>
>
>
>
>

<
<
<
>
|
|
<
>
>

>
>
>
>





|
|
|
|
|
|
|












>
>
>
>
>
>




|









|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











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




#
#	Name:             JIS X 0212 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#

#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#



#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.

#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       JIS X 0212 (1983) characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the JIS X 0212 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0212 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0212 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x6D63 -> 0x4D43 -> 7767
#
#   The kanji mappings are a normative part of ISO/IEC 10646.  The
#       non-kanji mappings are provisional, pending definition of
#       official mappings by Japanese standards bodies
#
#	Any comments or problems, contact <[email protected]>
#
#	Notes:
#
#	1. JIS X 0212 apparently unified the following two symbols
#	   into a single character at 0x2922:
#	
#	   LATIN CAPITAL LETTER D WITH STROKE
#	   LATIN CAPITAL LETTER ETH
#
#	   However, JIS X 0212 maintains the distinction between
#	   the lowercase forms of these two elements at 0x2942 and 0x2943.
#	   Given the structre of these JIS encodings, it is clear that
#	   0x2922 and 0x2942 are intended to be a capital/small pair.
#	   Consequently, in the Unicode mapping, 0x2922 is treated as
#	   LATIN CAPITAL LETTER D WITH STROKE.
#	  

















0x222F	0x02D8	# BREVE
0x2230	0x02C7	# CARON (Mandarin Chinese third tone)
0x2231	0x00B8	# CEDILLA
0x2232	0x02D9	# DOT ABOVE (Mandarin Chinese light tone)
0x2233	0x02DD	# DOUBLE ACUTE ACCENT
0x2234	0x00AF	# MACRON
0x2235	0x02DB	# OGONEK

Changes to tools/encoding/ksc5601.txt.

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
# What is enclosed below is the mapping between KS C 5601-1987
# and Unicode 2.0.   It's automatically generated from KSC5601.TXT
# (at ftp://ftp.unicode.org/Public/MAPPING/EASTASIA/KSC) which is
# actually NOT the mapping between KS C 5601-1992 and Unicode 2.0
# BUT the mapping table between UHC(Microsoft Unified Hangul Code)
# and Unicode 2.0. Hence, in this pacakge, I renamed it as UHC.TXT
#
# The Unix command  used is
# egrep '^0x' < KSC5601.TXT |   \
# egrep -v '^0x([8-9]...|A0..|..[4-9].|..A0)' | perl tab.pl
#
# where tab.pl  is as following
#----------tab.pl
#  $n=0;
#  while (<>) {
#    local($euck, $ucs4, @rest) = split;
#    local($u)=hex($ucs4);
#    local($k)=hex($euck);
#    printf ("0x%04X  0x%04X  %s\n",$k-0x8080, $u,join(' ',@rest));
#  }
#
# Column #1 : KS C 5601-1987(KS C 5601-1992 excluding addtional Hangul
#            syllables defined for Johab encoding in Annex 3)
#            in hex as 0xXXXX
# Column #2 : the Unicode (in hex as 0xXXXX)
# Column #3 : the Unicode name (following a comment sign, '#')
# The number of characters enumerated in this table is 8824, the
# as listed in KS C 5601-987
#
#
# The entries are in KS C 5601-1987 order
# You can use the following algorithms to convert the hex form
# of KS C 5601 to other forms
#   To get EUCKorea(EUC-KR) code points, add 0x8080.
#   To get row(Hang) and column(Yol) as used in KS C 5601-1987 manual,
#      first subtract 0x2020. Then
#      the high and low bytes correspond to the row(Hang) and the column(Yol),







|




















|
|







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
# What is enclosed below is the mapping between KS C 5601-1987
# and Unicode 2.0.   It's automatically generated from KSC5601.TXT
# (at ftp://ftp.unicode.org/Public/MAPPING/EASTASIA/KSC) which is
# actually NOT the mapping between KS C 5601-1992 and Unicode 2.0
# BUT the mapping table between UHC(Microsoft Unified Hangul Code)
# and Unicode 2.0. Hence, in this pacakge, I renamed it as UHC.TXT
#
# The Unix command  used is 
# egrep '^0x' < KSC5601.TXT |   \
# egrep -v '^0x([8-9]...|A0..|..[4-9].|..A0)' | perl tab.pl
#
# where tab.pl  is as following
#----------tab.pl
#  $n=0;
#  while (<>) {
#    local($euck, $ucs4, @rest) = split;
#    local($u)=hex($ucs4);
#    local($k)=hex($euck);
#    printf ("0x%04X  0x%04X  %s\n",$k-0x8080, $u,join(' ',@rest));
#  }
#
# Column #1 : KS C 5601-1987(KS C 5601-1992 excluding addtional Hangul
#            syllables defined for Johab encoding in Annex 3)
#            in hex as 0xXXXX
# Column #2 : the Unicode (in hex as 0xXXXX)
# Column #3 : the Unicode name (following a comment sign, '#')
# The number of characters enumerated in this table is 8824, the
# as listed in KS C 5601-987
# 
# 
# The entries are in KS C 5601-1987 order
# You can use the following algorithms to convert the hex form
# of KS C 5601 to other forms
#   To get EUCKorea(EUC-KR) code points, add 0x8080.
#   To get row(Hang) and column(Yol) as used in KS C 5601-1987 manual,
#      first subtract 0x2020. Then
#      the high and low bytes correspond to the row(Hang) and the column(Yol),

Changes to tools/encoding/macCentEuro.txt.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macCroatian.txt.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macCyrillic.txt.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macGreek.txt.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macIceland.txt.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macRoman.txt.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/macTurkish.txt.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#   throughout this document, "Macintosh" can be used to refer to
#   Macintosh computers and "Unicode" can be used to refer to the
#   Unicode standard.
#
#   Apple makes no warranty or representation, either express or
#   implied, with respect to these tables, their quality, accuracy, or
#   fitness for a particular purpose. In no event will Apple be liable
#   for direct, indirect, special, incidental, or consequential damages 
#   resulting from any defect or inaccuracy in this document or the
#   accompanying tables.
#
#   These mapping tables and character lists are subject to change.
#   The latest tables should be available from the following:
#
#   <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>

Changes to tools/encoding/shiftjis.txt.

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
# SHIFTJIS.TXT
# Date: 2015-12-02 23:52:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             Shift-JIS to Unicode
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#
#	General notes:

#







#
# This table contains one set of mappings from Shift-JIS into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited

# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of Shift-JIS and Unicode, consult the
# VENDORS mapping data.


#




#
#	Format:  Three tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are ordered by their Shift-JIS codes as follows:
#		Single-byte characters precede double-byte characters
#		The single-byte and double-byte blocks are in ascending
#		hexadecimal order
#	There is an alternative order some people might be preferred,
#		where all the entries are in order of the top (or only) byte.
#		This alternate order can be generated from the one given here
#		by a simple sort.
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.

#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
<
<
<
<



|

|
>
>

<
>

>
>
>
>
>
>
>

<
<
<
>
|
|
<
>
>

>
>
>
>





|
|
|
|
|
|
|








|

<
<
<
<
|
<
|
<
<
|

<
<
>

<
<











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




#
#	Name:             Shift-JIS to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#

#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#



#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.

#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       Shift-JIS (a combination of JIS 0201 and JIS 0208) maps into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#
#	The entries are ordered by their Shift-JIS codes as follows:
#		Single-byte characters precede double-byte characters
#		The single-byte and double-byte blocks are in ascending
#		hexadecimal order
#	There is an alternative order some people might be preferred,
#		where all the entries are in order of the top (or only) byte.
#		This alternate order can be generated from the one given here
#		by a simple sort.  
#




#   The kanji mappings are a normative part of ISO/IEC 10646.  The

#       non-kanji mappings are provisional, pending definition of


#       official mappings by Japanese standards bodies
#


#	Any comments or problems, contact <[email protected]>
#


#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Changes to tools/encoding/tis-620.txt.

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
0xA4	0x0E04 #THAI CHARACTER KHO KHWAI
0xA5	0x0E05 #THAI CHARACTER KHO KHON
0xA6	0x0E06 #THAI CHARACTER KHO RAKHANG
0xA7	0x0E07 #THAI CHARACTER NGO NGU
0xA8	0x0E08 #THAI CHARACTER CHO CHAN
0xA9	0x0E09 #THAI CHARACTER CHO CHING
0xAA	0x0E0A #THAI CHARACTER CHO CHANG
0xAB	0x0E0B #THAI CHARACTER SO SO
0xAC	0x0E0C #THAI CHARACTER CHO CHOE
0xAD	0x0E0D #THAI CHARACTER YO YING
0xAE	0x0E0E #THAI CHARACTER DO CHADA
0xAF	0x0E0F #THAI CHARACTER TO PATAK
0xB0	0x0E10 #THAI CHARACTER THO THAN
0xB1	0x0E11 #THAI CHARACTER THO NANGMONTHO
0xB2	0x0E12 #THAI CHARACTER THO PHUTHAO







|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
0xA4	0x0E04 #THAI CHARACTER KHO KHWAI
0xA5	0x0E05 #THAI CHARACTER KHO KHON
0xA6	0x0E06 #THAI CHARACTER KHO RAKHANG
0xA7	0x0E07 #THAI CHARACTER NGO NGU
0xA8	0x0E08 #THAI CHARACTER CHO CHAN
0xA9	0x0E09 #THAI CHARACTER CHO CHING
0xAA	0x0E0A #THAI CHARACTER CHO CHANG
0xAB	0x0E0B #THAI CHARACTER SO SO 
0xAC	0x0E0C #THAI CHARACTER CHO CHOE
0xAD	0x0E0D #THAI CHARACTER YO YING
0xAE	0x0E0E #THAI CHARACTER DO CHADA
0xAF	0x0E0F #THAI CHARACTER TO PATAK
0xB0	0x0E10 #THAI CHARACTER THO THAN
0xB1	0x0E11 #THAI CHARACTER THO NANGMONTHO
0xB2	0x0E12 #THAI CHARACTER THO PHUTHAO

Changes to tools/eolFix.tcl.

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

package provide EOL-fix 1.1

namespace eval ::EOL {
    variable outMode crlf
}

proc EOL::fix {filename {newfilename {}}} {
    variable outMode

    if {![file exists $filename]} {
	return
    }
    puts "EOL Fixing: $filename"

    file rename ${filename} ${filename}.o
    set fhnd [open ${filename}.o r]

    if {$newfilename ne ""} {
	set newfhnd [open ${newfilename} w]
    } else {
	set newfhnd [open ${filename} w]
    }

    fconfigure $newfhnd -translation [list auto $outMode]
    seek $fhnd 0 end







|


|
<
<





|







9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
27
28
29
30
31
32

package provide EOL-fix 1.1

namespace eval ::EOL {
    variable outMode crlf
}

proc EOL::fix {filename {newfilename ""}} {
    variable outMode

    if {![file exists $filename]} { return }


    puts "EOL Fixing: $filename"

    file rename ${filename} ${filename}.o
    set fhnd [open ${filename}.o r]

    if {$newfilename != ""} {
	set newfhnd [open ${newfilename} w]
    } else {
	set newfhnd [open ${filename} w]
    }

    fconfigure $newfhnd -translation [list auto $outMode]
    seek $fhnd 0 end
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

    foreach f [eval $cmd] {
	if {[file isfile $f]} {fix $f}
    }
}

if {$tcl_interactive == 0 && $argc > 0} {
    if {[string index [lindex $argv 0] 0] eq "-"} {
	switch -- [lindex $argv 0] {
	    -cr   {set ::EOL::outMode cr}
	    -crlf {set ::EOL::outMode crlf}
	    -lf   {set ::EOL::outMode lf}
	    default {puts stderr "improper mode switch"; exit 1}
        }
	set argv [lrange $argv 1 end]
    }
    eval EOL::fixall $argv
} else {
    return
}







|

|
|
|
|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

    foreach f [eval $cmd] {
	if {[file isfile $f]} {fix $f}
    }
}

if {$tcl_interactive == 0 && $argc > 0} {
    if {[string index [lindex $argv 0] 0] == "-"} {
	switch -- [lindex $argv 0] {
	    -cr   { set ::EOL::outMode cr }
	    -crlf { set ::EOL::outMode crlf }
	    -lf   { set ::EOL::outMode lf }
	    default { puts stderr "improper mode switch" ; exit 1 }
        }
	set argv [lrange $argv 1 end]
    }
    eval EOL::fixall $argv
} else {
    return
}

Changes to tools/findBadExternals.tcl.

1
2
3
4
5
6
7
8
9
# findBadExternals.tcl --
#
#	This script scans the Tcl load library for exported symbols
#	that do not begin with 'Tcl' or 'tcl'.  It reports them on the
#	standard output.  It is used to make sure that the library does
#	not inadvertently export externals that may be in conflict with
#	other code.
#
# Usage:

|







1
2
3
4
5
6
7
8
9
# findBadExternals.tcl --
# 
#	This script scans the Tcl load library for exported symbols
#	that do not begin with 'Tcl' or 'tcl'.  It reports them on the
#	standard output.  It is used to make sure that the library does
#	not inadvertently export externals that may be in conflict with
#	other code.
#
# Usage:
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39


    switch -exact -- $::tcl_platform(platform) {
	unix -
	macosx {
	    set status [catch {
		exec nm --extern-only --defined-only [lindex $argv 0]
	    } result]
	}
	windows {
	    set status [catch {
		exec dumpbin /exports [lindex $argv 0]
	    } result]
	}
    }







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39


    switch -exact -- $::tcl_platform(platform) {
	unix -
	macosx {
	    set status [catch {
		exec nm --extern-only --defined-only [lindex $argv 0]
	    } result] 
	}
	windows {
	    set status [catch {
		exec dumpbin /exports [lindex $argv 0]
	    } result]
	}
    }

Changes to tools/genStubs.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# genStubs.tcl --
#
#	This script generates a set of stub files for a given
#	interface.
#
#
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

namespace eval genStubs {
    # libraryName --






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# genStubs.tcl --
#
#	This script generates a set of stub files for a given
#	interface.
#
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2007 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

namespace eval genStubs {
    # libraryName --
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
    }
    regsub -all const $decl CONST decl
    regsub -all _XCONST $decl _Xconst decl
    regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
    set decl [parseDecl $decl]

    foreach platform $platformList {
	if {$decl ne ""} {
	    set stubs($curName,$platform,$index) $decl
	    if {![info exists stubs($curName,$platform,lastNum)] \
		    || ($index > $stubs($curName,$platform,lastNum))} {
		set stubs($curName,$platform,lastNum) $index
	    }
	}
    }







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
    }
    regsub -all const $decl CONST decl
    regsub -all _XCONST $decl _Xconst decl
    regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
    set decl [parseDecl $decl]

    foreach platform $platformList {
	if {$decl != ""} {
	    set stubs($curName,$platform,$index) $decl
	    if {![info exists stubs($curName,$platform,lastNum)] \
		    || ($index > $stubs($curName,$platform,lastNum))} {
		set stubs($curName,$platform,lastNum) $index
	    }
	}
    }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

proc genStubs::rewriteFile {file text} {
    if {![file exists $file]} {
	puts stderr "Cannot find file: $file"
	return
    }
    set in [open ${file} r]
    fconfigure $in -eofchar "\032 {}" -encoding utf-8
    set out [open ${file}.new w]
    fconfigure $out -translation lf -encoding utf-8

    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!BEGIN!*" $line]} {
	    break
	}
	puts $out $line







<

|







239
240
241
242
243
244
245

246
247
248
249
250
251
252
253
254

proc genStubs::rewriteFile {file text} {
    if {![file exists $file]} {
	puts stderr "Cannot find file: $file"
	return
    }
    set in [open ${file} r]

    set out [open ${file}.new w]
    fconfigure $out -translation lf

    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!BEGIN!*" $line]} {
	    break
	}
	puts $out $line
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
    }
    set prefix [string trim $prefix]
    if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
	puts stderr "Bad return type: $decl"
	return
    }
    set rtype [string trim $rtype]
    if {$args eq ""} {
	return [list $rtype $fname {}]
    }
    foreach arg [split $args ,] {
	lappend argList [string trim $arg]
    }
    if {![string compare [lindex $argList end] "..."]} {
	set args TCL_VARARGS







|







378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
    }
    set prefix [string trim $prefix]
    if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
	puts stderr "Bad return type: $decl"
	return
    }
    set rtype [string trim $rtype]
    if {$args == ""} {
	return [list $rtype $fname {}]
    }
    foreach arg [split $args ,] {
	lappend argList [string trim $arg]
    }
    if {![string compare [lindex $argList end] "..."]} {
	set args TCL_VARARGS
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
#
# Results:
#	Returns a list of type and name with an optional third array
#	indicator.  If the argument is malformed, returns "".

proc genStubs::parseArg {arg} {
    if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
	if {$arg eq "void"} {
	    return $arg
	} else {
	    return
	}
    }
    set result [list [string trim $type] $name]
    if {$array ne ""} {
	lappend result $array
    }
    return $result
}

# genStubs::makeDecl --
#







|






|







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
#
# Results:
#	Returns a list of type and name with an optional third array
#	indicator.  If the argument is malformed, returns "".

proc genStubs::parseArg {arg} {
    if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
	if {$arg == "void"} {
	    return $arg
	} else {
	    return
	}
    }
    set result [list [string trim $type] $name]
    if {$array != ""} {
	lappend result $array
    }
    return $result
}

# genStubs::makeDecl --
#
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#	Returns the formatted declaration string.

proc genStubs::makeDecl {name decl index} {
    variable scspec
    lassign $decl rtype fname args

    append text "/* $index */\n"
    if {$rtype ne "void"} {
	regsub -all void $rtype VOID rtype
    }
    set line "$scspec $rtype"
    set count [expr {2 - ([string length $line] / 8)}]
    if {$count >= 0} {
	append line [string range "\t\t\t" 0 $count]
    }
    set pad [expr {24 - [string length $line]}]
    if {$pad <= 0} {
	append line " "
	set pad 0
    }
    if {$args eq ""} {
	append line $fname







|




<
|
<







456
457
458
459
460
461
462
463
464
465
466
467

468

469
470
471
472
473
474
475
#	Returns the formatted declaration string.

proc genStubs::makeDecl {name decl index} {
    variable scspec
    lassign $decl rtype fname args

    append text "/* $index */\n"
    if {$rtype != "void"} {
	regsub -all void $rtype VOID rtype
    }
    set line "$scspec $rtype"
    set count [expr {2 - ([string length $line] / 8)}]

    append line [string range "\t\t\t" 0 $count]

    set pad [expr {24 - [string length $line]}]
    if {$pad <= 0} {
	append line " "
	set pad 0
    }
    if {$args eq ""} {
	append line $fname
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
proc genStubs::makeMacro {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "#ifndef $fname\n#define $fname \\\n\t("
    if {$args eq ""} {
	append text "*"
    }
    append text "${name}StubsPtr->$lfname)"
    append text " /* $index */\n#endif\n"
    return $text
}








|







548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
proc genStubs::makeMacro {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "#ifndef $fname\n#define $fname \\\n\t("
    if {$args == ""} {
	append text "*"
    }
    append text "${name}StubsPtr->$lfname)"
    append text " /* $index */\n#endif\n"
    return $text
}

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
proc genStubs::makeSlot {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "    "
    if {$args eq ""} {
	append text $rtype " *" $lfname "; /* $index */\n"
	return $text
    }
    if {$rtype ne "void"} {
	regsub -all void $rtype VOID rtype
    }
    if {[string range $rtype end-8 end] eq "__stdcall"} {
	append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") "
    } else {
	append text $rtype " (*" $lfname ") "
    }
    regsub -all void $args VOID args
    set arg1 [lindex $args 0]
    switch -exact $arg1 {







|






|







575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
proc genStubs::makeSlot {name decl index} {
    lassign $decl rtype fname args

    set lfname [string tolower [string index $fname 0]]
    append lfname [string range $fname 1 end]

    set text "    "
    if {$args == ""} {
	append text $rtype " *" $lfname "; /* $index */\n"
	return $text
    }
    if {$rtype ne "void"} {
	regsub -all void $rtype VOID rtype
    }
    if {[string range $rtype end-8 end] == "__stdcall"} {
	append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") "
    } else {
	append text $rtype " (*" $lfname ") "
    }
    regsub -all void $args VOID args
    set arg1 [lindex $args 0]
    switch -exact $arg1 {
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted declaration string.

proc genStubs::makeInit {name decl index} {
    if {[lindex $decl 2] eq ""} {
	append text "    &" [lindex $decl 1] ", /* " $index " */\n"
    } else {
	append text "    " [lindex $decl 1] ", /* " $index " */\n"
    }
    return $text
}








|







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
#	decl	The function declaration.
#	index	The slot index for this function.
#
# Results:
#	Returns the formatted declaration string.

proc genStubs::makeInit {name decl index} {
    if {[lindex $decl 2] == ""} {
	append text "    &" [lindex $decl 1] ", /* " $index " */\n"
    } else {
	append text "    " [lindex $decl 1] ", /* " $index " */\n"
    }
    return $text
}

981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
    variable hooks
    variable epoch
    variable revision

    set capName [string toupper [string index $name 0]]
    append capName [string range $name 1 end]

    if {$epoch ne ""} {
	set CAPName [string toupper $name]
	append text "\n"
	append text "#define ${CAPName}_STUBS_EPOCH $epoch\n"
	append text "#define ${CAPName}_STUBS_REVISION $revision\n"
    }

    append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"







|







978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
    variable hooks
    variable epoch
    variable revision

    set capName [string toupper [string index $name 0]]
    append capName [string range $name 1 end]

    if {$epoch != ""} {
	set CAPName [string toupper $name]
	append text "\n"
	append text "#define ${CAPName}_STUBS_EPOCH $epoch\n"
	append text "#define ${CAPName}_STUBS_REVISION $revision\n"
    }

    append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
	    append capHook [string range $hook 1 end]
	    append text "    struct ${capHook}Stubs *${hook}Stubs;\n"
	}
	append text "} ${capName}StubHooks;\n"
    }
    append text "\ntypedef struct ${capName}Stubs {\n"
    append text "    int magic;\n"
    if {$epoch ne ""} {
	append text "    int epoch;\n"
	append text "    int revision;\n"
    }
    append text "    struct ${capName}StubHooks *hooks;\n\n"

    emitSlots $name text








|







1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
	    append capHook [string range $hook 1 end]
	    append text "    struct ${capHook}Stubs *${hook}Stubs;\n"
	}
	append text "} ${capName}StubHooks;\n"
    }
    append text "\ntypedef struct ${capName}Stubs {\n"
    append text "    int magic;\n"
    if {$epoch != ""} {
	append text "    int epoch;\n"
	append text "    int revision;\n"
    }
    append text "    struct ${capName}StubHooks *hooks;\n\n"

    emitSlots $name text

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
	    append text $sep "&${sub}Stubs"
	    set sep ",\n    "
	}
	append text "\n\};\n"
    }
    append text "\n${capName}Stubs ${name}Stubs = \{\n"
    append text "    TCL_STUB_MAGIC,\n"
    if {$epoch ne ""} {
	set CAPName [string toupper $name]
	append text "    ${CAPName}_STUBS_EPOCH,\n"
	append text "    ${CAPName}_STUBS_REVISION,\n"
    }
    if {[info exists hooks($name)]} {
	append text "    &${name}StubHooks,\n"
    } else {







|







1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
	    append text $sep "&${sub}Stubs"
	    set sep ",\n    "
	}
	append text "\n\};\n"
    }
    append text "\n${capName}Stubs ${name}Stubs = \{\n"
    append text "    TCL_STUB_MAGIC,\n"
    if {$epoch != ""} {
	set CAPName [string toupper $name]
	append text "    ${CAPName}_STUBS_EPOCH,\n"
	append text "    ${CAPName}_STUBS_REVISION,\n"
    }
    if {[info exists hooks($name)]} {
	append text "    &${name}StubHooks,\n"
    } else {
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
	puts stderr "usage: $argv0 outDir declFile ?declFile...?"
	exit 1
    }

    set outDir [lindex $argv 0]

    foreach file [lrange $argv 1 end] {
	source -encoding utf-8 $file
    }

    foreach name [lsort [array names interfaces]] {
	puts "Emitting $name"
	emitHeader $name
    }








|







1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
	puts stderr "usage: $argv0 outDir declFile ?declFile...?"
	exit 1
    }

    set outDir [lindex $argv 0]

    foreach file [lrange $argv 1 end] {
	source $file
    }

    foreach name [lsort [array names interfaces]] {
	puts "Emitting $name"
	emitHeader $name
    }

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
# Arguments:
#	valueList	A list containing the values to be assigned.
#	args		The list of variables to be assigned.
#
# Results:
#	Returns any values that were not assigned to variables.

if {[namespace which lassign] ne ""} {
    proc lassign {valueList args} {
	if {[llength $args] == 0} {
	    error "wrong # args: should be \"lassign list varName ?varName ...?\""
	}
	uplevel [list foreach $args $valueList {break}]
	return [lrange $valueList [llength $args] end]
    }
}

genStubs::init







|










1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
# Arguments:
#	valueList	A list containing the values to be assigned.
#	args		The list of variables to be assigned.
#
# Results:
#	Returns any values that were not assigned to variables.

if {[string length [namespace which lassign]] == 0} {
    proc lassign {valueList args} {
	if {[llength $args] == 0} {
	    error "wrong # args: should be \"lassign list varName ?varName ...?\""
	}
	uplevel [list foreach $args $valueList {break}]
	return [lrange $valueList [llength $args] end]
    }
}

genStubs::init

Changes to tools/index.tcl.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#				
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
proc macro {name args} {
    switch $name {
	SH - SS {
	    global state

	    switch $args {
		NAME {
		    if {$state eq "INIT" } {
			set state NAME
		    }
		}
		DESCRIPTION {set state DT}
		INTRODUCTION {set state DT}
		KEYWORDS {set state KEY}
		default {set state OFF}
	    }

	}
	TH {
	    global state curID curPkg curSect topics keywords
	    set state INIT
	    if {[llength $args] != 5} {
		set args [join $args " "]
		puts stderr "Bad .TH macro: .$name $args"







|








|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
proc macro {name args} {
    switch $name {
	SH - SS {
	    global state

	    switch $args {
		NAME {
		    if {$state == "INIT" } {
			set state NAME
		    }
		}
		DESCRIPTION {set state DT}
		INTRODUCTION {set state DT}
		KEYWORDS {set state KEY}
		default {set state OFF}
	    }
	    
	}
	TH {
	    global state curID curPkg curSect topics keywords
	    set state INIT
	    if {[llength $args] != 5} {
		set args [join $args " "]
		puts stderr "Bad .TH macro: .$name $args"
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# troff).  It only function in pass1 is to terminate the NAME state.
#
# Arguments:
# None.

proc dash {} {
    global state
    if {$state eq "NAME"} {
	set state DASH
    }
}



# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass.
#
# Arguments:
# None.

proc initGlobals {} {}
proc newline {} {}
proc tab {} {}
proc font type {}
proc char name {}
proc macro2 {name args} {}








|








|











172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# troff).  It only function in pass1 is to terminate the NAME state.
#
# Arguments:
# None.

proc dash {} {
    global state
    if {$state == "NAME"} {
	set state DASH
    }
}



# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass. 
#
# Arguments:
# None.

proc initGlobals {} {}
proc newline {} {}
proc tab {} {}
proc font type {}
proc char name {}
proc macro2 {name args} {}

Changes to tools/loadICU.tcl.

428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
    if { [info exists format($localeName,TIME_FORMAT)]
	 || [info exists items(DateTimePatterns)] } {

	# Find the shortest time pattern that includes the seconds

	if { ![info exists format($localeName,TIME_FORMAT)] } {
	    for { set i 3 } { $i >= 0 } { incr i -1 } {
		if { [regexp H [lindex $items(DateTimePatterns) $i]]
		     && [regexp s [lindex $items(DateTimePatterns) $i]] } {
		    break
		}
	    }
	    if { $i >= 0 } {
		set fmt \
		    [backslashify \







|







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
    if { [info exists format($localeName,TIME_FORMAT)]
	 || [info exists items(DateTimePatterns)] } {

	# Find the shortest time pattern that includes the seconds

	if { ![info exists format($localeName,TIME_FORMAT)] } {
	    for { set i 3 } { $i >= 0 } { incr i -1 } {
		if { [regexp H [lindex $items(DateTimePatterns) $i]] 
		     && [regexp s [lindex $items(DateTimePatterns) $i]] } {
		    break
		}
	    }
	    if { $i >= 0 } {
		set fmt \
		    [backslashify \
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
    if { [info exists format($localeName,TIME_FORMAT_12)]
	 || [info exists items(DateTimePatterns)] } {

	# Shortest patterm with 12-hour time that includes seconds

	if { ![info exists format($localeName,TIME_FORMAT_12)] } {
	    for { set i 3 } { $i >= 0 } { incr i -1 } {
		if { [regexp h [lindex $items(DateTimePatterns) $i]]
		     && [regexp s [lindex $items(DateTimePatterns) $i]] } {
		    break
		}
	    }
	    if { $i >= 0 } {
		set fmt \
		    [backslashify \







|







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
    if { [info exists format($localeName,TIME_FORMAT_12)]
	 || [info exists items(DateTimePatterns)] } {

	# Shortest patterm with 12-hour time that includes seconds

	if { ![info exists format($localeName,TIME_FORMAT_12)] } {
	    for { set i 3 } { $i >= 0 } { incr i -1 } {
		if { [regexp h [lindex $items(DateTimePatterns) $i]] 
		     && [regexp s [lindex $items(DateTimePatterns) $i]] } {
		    break
		}
	    }
	    if { $i >= 0 } {
		set fmt \
		    [backslashify \
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
		$format($localeName,TIME_FORMAT_12) "\""
	    puts $f $cmd
	}
    }

    # Date and time... Prefer 24-hour format to 12-hour format.

    if { ![info exists format($localeName,DATE_TIME_FORMAT)]
	 && [info exists format($localeName,DATE_FORMAT)]
	 && [info exists format($localeName,TIME_FORMAT)]} {
	set format($localeName,DATE_TIME_FORMAT) \
	    $format($localeName,DATE_FORMAT)
	append format($localeName,DATE_TIME_FORMAT) \
	    " " $format($localeName,TIME_FORMAT) " %z"
    }
    if { ![info exists format($localeName,DATE_TIME_FORMAT)]
	 && [info exists format($localeName,DATE_FORMAT)]
	 && [info exists format($localeName,TIME_FORMAT_12)]} {
	set format($localeName,DATE_TIME_FORMAT) \
	    $format($localeName,DATE_FORMAT)
	append format($localeName,DATE_TIME_FORMAT) \
	    " " $format($localeName,TIME_FORMAT_12) " %z"
    }

    # Write date/time format to the file

    if { [info exists format($localeName,DATE_TIME_FORMAT)] } {
	set cmd "    ::msgcat::mcset "
	append cmd $localeName " DATE_TIME_FORMAT \"" \
	    $format($localeName,DATE_TIME_FORMAT) "\""
	puts $f $cmd
    }

    # Write the string sets to the file.

    foreach key {
	LOCALE_NUMERALS LOCALE_DATE_FORMAT LOCALE_TIME_FORMAT
	LOCALE_DATE_TIME_FORMAT LOCALE_ERAS LOCALE_YEAR_FORMAT
    } {
	if { [info exists format($localeName,$key)] } {
	    set cmd "    ::msgcat::mcset "
	    append cmd $localeName " " $key " \"" \
		[backslashify $format($localeName,$key)] "\""







|







|



















|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
		$format($localeName,TIME_FORMAT_12) "\""
	    puts $f $cmd
	}
    }

    # Date and time... Prefer 24-hour format to 12-hour format.

    if { ![info exists format($localeName,DATE_TIME_FORMAT)] 
	 && [info exists format($localeName,DATE_FORMAT)]
	 && [info exists format($localeName,TIME_FORMAT)]} {
	set format($localeName,DATE_TIME_FORMAT) \
	    $format($localeName,DATE_FORMAT)
	append format($localeName,DATE_TIME_FORMAT) \
	    " " $format($localeName,TIME_FORMAT) " %z"
    }
    if { ![info exists format($localeName,DATE_TIME_FORMAT)] 
	 && [info exists format($localeName,DATE_FORMAT)]
	 && [info exists format($localeName,TIME_FORMAT_12)]} {
	set format($localeName,DATE_TIME_FORMAT) \
	    $format($localeName,DATE_FORMAT)
	append format($localeName,DATE_TIME_FORMAT) \
	    " " $format($localeName,TIME_FORMAT_12) " %z"
    }

    # Write date/time format to the file

    if { [info exists format($localeName,DATE_TIME_FORMAT)] } {
	set cmd "    ::msgcat::mcset "
	append cmd $localeName " DATE_TIME_FORMAT \"" \
	    $format($localeName,DATE_TIME_FORMAT) "\""
	puts $f $cmd
    }

    # Write the string sets to the file.

    foreach key { 
	LOCALE_NUMERALS LOCALE_DATE_FORMAT LOCALE_TIME_FORMAT
	LOCALE_DATE_TIME_FORMAT LOCALE_ERAS LOCALE_YEAR_FORMAT
    } {
	if { [info exists format($localeName,$key)] } {
	    set cmd "    ::msgcat::mcset "
	    append cmd $localeName " " $key " \"" \
		[backslashify $format($localeName,$key)] "\""
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
#----------------------------------------------------------------------

proc backslashify { string } {

    set retval {}
    foreach char [split $string {}] {
	scan $char %c ccode
	if { $ccode >= 0x20 && $ccode < 0x7F && $char ne "\""
	     && $char ne "\{" && $char ne "\}" && $char ne "\["
	     && $char ne "\]" && $char ne "\\" && $char ne "\$" } {
	    append retval $char
	} else {
	    append retval \\u [format %04x $ccode]
	}
    }







|







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
#----------------------------------------------------------------------

proc backslashify { string } {

    set retval {}
    foreach char [split $string {}] {
	scan $char %c ccode
	if { $ccode >= 0x0020 && $ccode < 0x007f && $char ne "\"" 
	     && $char ne "\{" && $char ne "\}" && $char ne "\["
	     && $char ne "\]" && $char ne "\\" && $char ne "\$" } {
	    append retval $char
	} else {
	    append retval \\u [format %04x $ccode]
	}
    }

Changes to tools/makeTestCases.tcl.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	    x xi xii xiii xiv xv xvi xvii xviii xix
	    xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
	    xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
	    xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
	    l li lii liii liv lv lvi lvii lviii lix
	    lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
	    lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
	    lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii
	    lxxxix
	    xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
	    c
	}
	DATE_FORMAT {%m/%d/%Y}
	TIME_FORMAT {%H:%M:%S}
	DATE_TIME_FORMAT {%x %X}







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	    x xi xii xiii xiv xv xvi xvii xviii xix
	    xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
	    xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
	    xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
	    l li lii liii liv lv lvi lvii lviii lix
	    lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
	    lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
	    lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii 
	    lxxxix
	    xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
	    c
	}
	DATE_FORMAT {%m/%d/%Y}
	TIME_FORMAT {%H:%M:%S}
	DATE_TIME_FORMAT {%x %X}
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#
# listYears --
#
#	List the years to test in the common clock test cases.
#
# Parameters:
#	startOfYearArray - Name of an array in caller's scope that will
#	                   be initialized as
# Results:
#       None
#
# Side effects:
#	Determines the year numbers of one common year, one leap year, one year
#	following a common year, and one year following a leap year -- starting
#	on each day of the week -- in the XIXth, XXth and XXIth centuries.







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#
# listYears --
#
#	List the years to test in the common clock test cases.
#
# Parameters:
#	startOfYearArray - Name of an array in caller's scope that will
#	                   be initialized as 
# Results:
#       None
#
# Side effects:
#	Determines the year numbers of one common year, one leap year, one year
#	following a common year, and one year following a leap year -- starting
#	on each day of the week -- in the XIXth, XXth and XXIth centuries.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	    set do($x$c$dw$l) $y
	    set startOfYear($y) $s
	    set startOfYear([expr {$y + 1}]) $s2
	}
	set s $s2
	incr y
    }

    # List years before 1970

    set y 1970
    set s 0
    set dw 4; # Thursday
    while { $y >= 1801 } {
	set s0 $s







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	    set do($x$c$dw$l) $y
	    set startOfYear($y) $s
	    set startOfYear([expr {$y + 1}]) $s2
	}
	set s $s2
	incr y
    }
    
    # List years before 1970

    set y 1970
    set s 0
    set dw 4; # Thursday
    while { $y >= 1801 } {
	set s0 $s
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
	}
    }

}

#----------------------------------------------------------------------
#
# processFile -
#
#	Processes the 'clock.test' file, updating the test cases in it.
#
# Parameters:
#	None.
#
# Side effects:
#	Replaces the file with a new copy, constructing needed test cases.
#
#----------------------------------------------------------------------

proc processFile {d} {

    # Open two files

    set f1 [open [file join $d tests/clock.test] r]
    set f2 [open [file join $d tests/clock.new] w]

    # Copy leading portion of the test file

    set state {}
    while { [gets $f1 line] >= 0 } {
	switch -exact -- $state {
	    {} {
		puts $f2 $line
		if { [regexp "^\# BEGIN (.*)" $line -> cases]
		     && [string compare {} [info commands $cases]] } {
		    set state inCaseSet
		    $cases $f2
		}
	    }
	    inCaseSet {
		if { [regexp "^\#\ END $cases\$" $line] } {







|














|










|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
	}
    }

}

#----------------------------------------------------------------------
#
# processFile - 
#
#	Processes the 'clock.test' file, updating the test cases in it.
#
# Parameters:
#	None.
#
# Side effects:
#	Replaces the file with a new copy, constructing needed test cases.
#
#----------------------------------------------------------------------

proc processFile {d} {

    # Open two files
    
    set f1 [open [file join $d tests/clock.test] r]
    set f2 [open [file join $d tests/clock.new] w]

    # Copy leading portion of the test file

    set state {}
    while { [gets $f1 line] >= 0 } {
	switch -exact -- $state {
	    {} {
		puts $f2 $line
		if { [regexp "^\# BEGIN (.*)" $line -> cases] 
		     && [string compare {} [info commands $cases]] } {
		    set state inCaseSet
		    $cases $f2
		}
	    }
	    inCaseSet {
		if { [regexp "^\#\ END $cases\$" $line] } {
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#----------------------------------------------------------------------

proc testcases2 { f2 } {

    listYears startOfYear

    # Define the roman numerals

    set roman {
 	? i ii iii iv v vi vii viii ix
	x xi xii xiii xiv xv xvi xvii xviii xix
	xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
	xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
	xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
	l li lii liii liv lv lvi lvii lviii lix







|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#----------------------------------------------------------------------

proc testcases2 { f2 } {

    listYears startOfYear

    # Define the roman numerals
    
    set roman {
 	? i ii iii iv v vi vii viii ix
	x xi xii xiii xiv xv xvi xvii xviii xix
	xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
	xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
	xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
	l li lii liii liv lv lvi lvii lviii lix
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
 	? c cc ccc cd d dc dcc dccc cm
	m mc mcc mccc mcd md mdc mdcc mdccc mcm
	mm mmc mmcc mmccc mmcd mmd mmdc mmdcc mmdccc mmcm
	mmm mmmc mmmcc mmmccc mmmcd mmmd mmmdc mmmdcc mmmdccc mmmcm
    }

    # Names of the months

    set short {{} Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}
    set long {
	{} January February March April May June July August September
	October November December
    }

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test formatting of Gregorian year, month, day, all formats"
    puts $f2 "\# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY"
    puts $f2 ""

    # Generate the test cases for the first and last day of every month
    # from 1896 to 2045

    set n 0
    foreach { y } [lsort -integer [array names startOfYear]] {
	set s [expr { $startOfYear($y) + wide(12*3600 + 34*60 + 56) }]
	set m 0
	set yd 1
	foreach hath { 31 28 31 30 31 30 31 31 30 31 30 31 } {
	    incr m
	    if { $m == 2 && ( $y%4 == 0 && $y%100 != 0 || $y%400 == 0 ) } {
		incr hath
	    }

	    set b [lindex $short $m]
	    set B [lindex $long $m]
	    set C [format %02d [expr { $y / 100 }]]
	    set h $b
	    set j [format %03d $yd]
	    set mm [format %02d $m]
	    set N [format %2d $m]
	    set yy [format %02d [expr { $y % 100 }]]

	    set J [expr { ( $s / 86400 ) + 2440588 }]

	    set dt $y-$mm-01
	    set result ""
	    append result $b " " $B " " \
		$mm /01/ $y " 12:34:56 " \
		"die i mensis " [lindex $roman $m] " annoque " \
		[lindex $romanc [expr { $y / 100 }]] \
		[lindex $roman [expr { $y % 100 }]] " " \







|





|

|




|













|








|

|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
 	? c cc ccc cd d dc dcc dccc cm
	m mc mcc mccc mcd md mdc mdcc mdccc mcm
	mm mmc mmcc mmccc mmcd mmd mmdc mmdcc mmdccc mmcm
	mmm mmmc mmmcc mmmccc mmmcd mmmd mmmdc mmmdcc mmmdccc mmmcm
    }

    # Names of the months
    
    set short {{} Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}
    set long {
	{} January February March April May June July August September
	October November December
    }
    
    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test formatting of Gregorian year, month, day, all formats"
    puts $f2 "\# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY"
    puts $f2 ""
    
    # Generate the test cases for the first and last day of every month
    # from 1896 to 2045

    set n 0
    foreach { y } [lsort -integer [array names startOfYear]] {
	set s [expr { $startOfYear($y) + wide(12*3600 + 34*60 + 56) }]
	set m 0
	set yd 1
	foreach hath { 31 28 31 30 31 30 31 31 30 31 30 31 } {
	    incr m
	    if { $m == 2 && ( $y%4 == 0 && $y%100 != 0 || $y%400 == 0 ) } {
		incr hath
	    }
	    
	    set b [lindex $short $m]
	    set B [lindex $long $m]
	    set C [format %02d [expr { $y / 100 }]]
	    set h $b
	    set j [format %03d $yd]
	    set mm [format %02d $m]
	    set N [format %2d $m]
	    set yy [format %02d [expr { $y % 100 }]]
	    
	    set J [expr { ( $s / 86400 ) + 2440588 }]
	    
	    set dt $y-$mm-01
	    set result ""
	    append result $b " " $B " " \
		$mm /01/ $y " 12:34:56 " \
		"die i mensis " [lindex $roman $m] " annoque " \
		[lindex $romanc [expr { $y / 100 }]] \
		[lindex $roman [expr { $y % 100 }]] " " \
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
		[lindex $roman [expr { $y % 100 }]]	\
		" " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
	    puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
	    puts $f2 "    clock format $s \\"
	    puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
	    puts $f2 "\t-gmt true -locale en_US_roman"
	    puts $f2 "} {$result}"

	    set hm1 [expr { $hath - 1 }]
	    incr s [expr { 86400 * ( $hath - 1 ) }]
	    incr yd $hm1

	    set dd [format %02d $hath]
	    set ee [format %2d $hath]
	    set j [format %03d $yd]

	    set J [expr { ( $s / 86400 ) + 2440588 }]

	    set dt $y-$mm-$dd
	    set result ""
	    append result $b " " $B " " \
		$mm / $dd / $y " 12:34:56 " \
		"die " [lindex $roman $hath] " mensis " [lindex $roman $m] \
		" annoque " \
		[lindex $romanc [expr { $y / 100 }]] \







|



|



|

|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
		[lindex $roman [expr { $y % 100 }]]	\
		" " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
	    puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
	    puts $f2 "    clock format $s \\"
	    puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
	    puts $f2 "\t-gmt true -locale en_US_roman"
	    puts $f2 "} {$result}"
	    
	    set hm1 [expr { $hath - 1 }]
	    incr s [expr { 86400 * ( $hath - 1 ) }]
	    incr yd $hm1
	    
	    set dd [format %02d $hath]
	    set ee [format %2d $hath]
	    set j [format %03d $yd]
	    
	    set J [expr { ( $s / 86400 ) + 2440588 }]
	    
	    set dt $y-$mm-$dd
	    set result ""
	    append result $b " " $B " " \
		$mm / $dd / $y " 12:34:56 " \
		"die " [lindex $roman $hath] " mensis " [lindex $roman $m] \
		" annoque " \
		[lindex $romanc [expr { $y / 100 }]] \
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
		[lindex $roman [expr { $y % 100 }]]	\
		" " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
	    puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
	    puts $f2 "    clock format $s \\"
	    puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
	    puts $f2 "\t-gmt true -locale en_US_roman"
	    puts $f2 "} {$result}"

	    incr s 86400
	    incr yd
	}
    }
    puts "testcases2: $n test cases"
}








|







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
		[lindex $roman [expr { $y % 100 }]]	\
		" " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
	    puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
	    puts $f2 "    clock format $s \\"
	    puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
	    puts $f2 "\t-gmt true -locale en_US_roman"
	    puts $f2 "} {$result}"
	    
	    incr s 86400
	    incr yd
	}
    }
    puts "testcases2: $n test cases"
}

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
		    testISO $f2 $ym1 53 1 [expr { $secs - 5*86400 }]
		    testISO $f2 $ym1 53 6 $secs
		    testISO $f2 $ym1 53 7 [expr { $secs + 86400 }]
		} else {
		    testISO $f2 $ym1 52 1 [expr { $secs - 5*86400 }]
		    testISO $f2 $ym1 52 6 $secs
		    testISO $f2 $ym1 52 7 [expr { $secs + 86400 }]
		}
		testISO $f2 $y 1 1 [expr { $secs + 2*86400 }]
		testISO $f2 $y 1 6 [expr { $secs + 7*86400 }]
		testISO $f2 $y 1 7 [expr { $secs + 8*86400 }]
		testISO $f2 $y 2 1 [expr { $secs + 9*86400 }]
	    }
	}
    }
    puts "testcases3: $case test cases."

}

proc testISO { f2 G V u secs } {

    upvar 1 case case

    set longdays {Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
    set shortdays {Sun Mon Tue Wed Thu Fri Sat Sun}

    puts $f2 "test clock-3.[incr case] {ISO week-based calendar [format %04d-W%02d-%d $G $V $u]} {"
    puts $f2 "    clock format $secs -format {%a %A %g %G %u %U %V %w %W} -gmt true; \# $G-W[format %02d $V]-$u"
    puts $f2 "} {[lindex $shortdays $u] [lindex $longdays $u]\
             [format %02d [expr { $G % 100 }]] $G\
             $u\
             [clock format $secs -format %U -gmt true]\
             [format %02d $V] [expr { $u % 7 }]\
             [clock format $secs -format %W -gmt true]}"

}

#----------------------------------------------------------------------
#
# testcases4 --
#
#	Makes the test cases that test formatting of time of day.







|














|


|








|







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
		    testISO $f2 $ym1 53 1 [expr { $secs - 5*86400 }]
		    testISO $f2 $ym1 53 6 $secs
		    testISO $f2 $ym1 53 7 [expr { $secs + 86400 }]
		} else {
		    testISO $f2 $ym1 52 1 [expr { $secs - 5*86400 }]
		    testISO $f2 $ym1 52 6 $secs
		    testISO $f2 $ym1 52 7 [expr { $secs + 86400 }]
		}		    
		testISO $f2 $y 1 1 [expr { $secs + 2*86400 }]
		testISO $f2 $y 1 6 [expr { $secs + 7*86400 }]
		testISO $f2 $y 1 7 [expr { $secs + 8*86400 }]
		testISO $f2 $y 2 1 [expr { $secs + 9*86400 }]
	    }
	}
    }
    puts "testcases3: $case test cases."

}

proc testISO { f2 G V u secs } {

    upvar 1 case case
    
    set longdays {Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
    set shortdays {Sun Mon Tue Wed Thu Fri Sat Sun}
    
    puts $f2 "test clock-3.[incr case] {ISO week-based calendar [format %04d-W%02d-%d $G $V $u]} {"
    puts $f2 "    clock format $secs -format {%a %A %g %G %u %U %V %w %W} -gmt true; \# $G-W[format %02d $V]-$u"
    puts $f2 "} {[lindex $shortdays $u] [lindex $longdays $u]\
             [format %02d [expr { $G % 100 }]] $G\
             $u\
             [clock format $secs -format %U -gmt true]\
             [format %02d $V] [expr { $u % 7 }]\
             [clock format $secs -format %W -gmt true]}"
    
}

#----------------------------------------------------------------------
#
# testcases4 --
#
#	Makes the test cases that test formatting of time of day.
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

proc testcases4 { f2 } {

    puts $f2 {}
    puts $f2 "\# Test formatting of time of day"
    puts $f2 "\# Format groups tested: %H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
    puts $f2 {}

    set i 0
    set fmt "%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
    foreach { h romanH I romanI am } {
	0 ? 12 xii AM
	1 i 1 i AM
	11 xi 11 xi AM
	12 xii 12 xii PM
	13 xiii 1 i PM
	23 xxiii 11 xi PM
    } {
	set hh [format %02d $h]
	set II [format %02d $I]
	set hs [format %2d $h]
	set Is [format %2d $I]
	foreach { m romanM } { 0 ? 1 i 58 lviii 59 lix } {







|


|
|
|
|
|
|







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

proc testcases4 { f2 } {

    puts $f2 {}
    puts $f2 "\# Test formatting of time of day"
    puts $f2 "\# Format groups tested: %H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
    puts $f2 {}
    
    set i 0
    set fmt "%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
    foreach { h romanH I romanI am } { 
	0 ? 12 xii AM 
	1 i 1 i AM 
	11 xi 11 xi AM 
	12 xii 12 xii PM 
	13 xiii 1 i PM 
	23 xxiii 11 xi PM
    } {
	set hh [format %02d $h]
	set II [format %02d $I]
	set hs [format %2d $h]
	set Is [format %2d $I]
	foreach { m romanM } { 0 ? 1 i 58 lviii 59 lix } {
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
		puts $f2 "} {$result}"
	    }
	}
    }

    puts "testcases4: $i test cases."
}

#----------------------------------------------------------------------
#
# testcases5 --
#
#	Generates the test cases for Daylight Saving Time
#
# Parameters:







|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
		puts $f2 "} {$result}"
	    }
	}
    }

    puts "testcases4: $i test cases."
}
    
#----------------------------------------------------------------------
#
# testcases5 --
#
#	Generates the test cases for Daylight Saving Time
#
# Parameters:
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

proc testcases5 { f2 } {
    variable TZData

    puts $f2 {}
    puts $f2 "\# Test formatting of Daylight Saving Time"
    puts $f2 {}

    set fmt {%H:%M:%S %z %Z}

    set i 0
    puts $f2 "test clock-5.[incr i] {does Detroit exist} {"
    puts $f2 "    clock format 0 -format {} -timezone :America/Detroit"
    puts $f2 "    concat"
    puts $f2 "} {}"
    puts $f2 "test clock-5.[incr i] {does Detroit have a Y2038 problem} detroit {"
    puts $f2 "    if { \[clock format 2158894800 -format %z -timezone :America/Detroit\] ne {-0400} } {"
    puts $f2 "        concat {y2038 problem}"
    puts $f2 "    } else {"
    puts $f2 "        concat {ok}"
    puts $f2 "    }"
    puts $f2 "} ok"

    foreach row $TZData(:America/Detroit) {
	foreach { t offset isdst tzname } $row break
	if { $t > -4000000000000 } {
	    set conds [list detroit]
	    if { $t > wide(0x7FFFFFFF) } {
		set conds [list detroit y2038]
	    }
	    incr t -1
	    set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \
		       -timezone :America/Detroit]
	    set r [clock format $t -format $fmt \
		       -timezone :America/Detroit]







|

|












|




|







568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

proc testcases5 { f2 } {
    variable TZData

    puts $f2 {}
    puts $f2 "\# Test formatting of Daylight Saving Time"
    puts $f2 {}
    
    set fmt {%H:%M:%S %z %Z}
    
    set i 0
    puts $f2 "test clock-5.[incr i] {does Detroit exist} {"
    puts $f2 "    clock format 0 -format {} -timezone :America/Detroit"
    puts $f2 "    concat"
    puts $f2 "} {}"
    puts $f2 "test clock-5.[incr i] {does Detroit have a Y2038 problem} detroit {"
    puts $f2 "    if { \[clock format 2158894800 -format %z -timezone :America/Detroit\] ne {-0400} } {"
    puts $f2 "        concat {y2038 problem}"
    puts $f2 "    } else {"
    puts $f2 "        concat {ok}"
    puts $f2 "    }"
    puts $f2 "} ok"
  
    foreach row $TZData(:America/Detroit) {
	foreach { t offset isdst tzname } $row break
	if { $t > -4000000000000 } {
	    set conds [list detroit]
	    if { $t > wide(0x7fffffff) } {
		set conds [list detroit y2038]
	    }
	    incr t -1
	    set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \
		       -timezone :America/Detroit]
	    set r [clock format $t -format $fmt \
		       -timezone :America/Detroit]
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
#	output file.
#
#----------------------------------------------------------------------

proc testcases8 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of ccyymmdd"
    puts $f2 ""

    set n 0
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach ccyy {%C%y %Y} {
		    foreach mm {%b %B %h %m %Om %N} {
			foreach dd {%d %Od %e %Oe} {
			    set string [clock format $scanned \
					    -format "$ccyy $mm $dd" \
					    -locale en_US_roman \
					    -gmt true]
			    puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
			    puts $f2 "    [list clock scan $string -format [list $ccyy $mm $dd] -locale en_US_roman -gmt 1]"
			    puts $f2 "} $scanned"
			}
		    }
		}
		foreach fmt {%x %D} {
		    set string [clock format $scanned \
				    -format $fmt \
				    -locale en_US_roman \
				    -gmt true]
		    puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
		    puts $f2 "    [list clock scan $string -format $fmt -locale en_US_roman -gmt 1]"







|



|
|
















|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
#	output file.
#
#----------------------------------------------------------------------

proc testcases8 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of ccyymmdd"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach ccyy {%C%y %Y} {
		    foreach mm {%b %B %h %m %Om %N} {
			foreach dd {%d %Od %e %Oe} {
			    set string [clock format $scanned \
					    -format "$ccyy $mm $dd" \
					    -locale en_US_roman \
					    -gmt true]
			    puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
			    puts $f2 "    [list clock scan $string -format [list $ccyy $mm $dd] -locale en_US_roman -gmt 1]"
			    puts $f2 "} $scanned"
			}
		    }
		}	
		foreach fmt {%x %D} {
		    set string [clock format $scanned \
				    -format $fmt \
				    -locale en_US_roman \
				    -gmt true]
		    puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
		    puts $f2 "    [list clock scan $string -format $fmt -locale en_US_roman -gmt 1]"
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
#	to f2.
#
#----------------------------------------------------------------------

proc testcases11 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test precedence among yyyymmdd and yyyyddd"
    puts $f2 ""

    array set v {
	Y 1970
	m 01
	d 01
	j 002
    }








|



|







704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
#	to f2.
#
#----------------------------------------------------------------------

proc testcases11 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test precedence among yyyymmdd and yyyyddd"
    puts $f2 ""
    
    array set v {
	Y 1970
	m 01
	d 01
	j 002
    }

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
#	output file.
#
#----------------------------------------------------------------------

proc testcases12 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of ccyyWwwd"
    puts $f2 ""

    set n 0
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \
				    -format "%G W%V $d" \







|



|
|







767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
#	output file.
#
#----------------------------------------------------------------------

proc testcases12 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of ccyyWwwd"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \
				    -format "%G W%V $d" \
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
#	Test cases for parsing yymmdd dates are output.
#
#----------------------------------------------------------------------

proc testcases14 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of yymmdd"
    puts $f2 ""

    set n 0
    foreach year {1938 1970 2000 2037} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach yy {%y %Oy} {
		    foreach mm {%b %B %h %m %Om %N} {
			foreach dd {%d %Od %e %Oe} {
			    set string [clock format $scanned \
					    -format "$yy $mm $dd" \
					    -locale en_US_roman \
					    -gmt true]
			    puts $f2 "test clock-14.[incr n] {parse yymmdd} {"
			    puts $f2 "    [list clock scan $string -format [list $yy $mm $dd] -locale en_US_roman -gmt 1]"
			    puts $f2 "} $scanned"
			}
		    }
		}
	    }
	}
    }

    puts "testcases14: $n test cases"
}








|



|
|
















|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
#	Test cases for parsing yymmdd dates are output.
#
#----------------------------------------------------------------------

proc testcases14 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of yymmdd"
    puts $f2 ""
    
    set n 0 
    foreach year {1938 1970 2000 2037} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach yy {%y %Oy} {
		    foreach mm {%b %B %h %m %Om %N} {
			foreach dd {%d %Od %e %Oe} {
			    set string [clock format $scanned \
					    -format "$yy $mm $dd" \
					    -locale en_US_roman \
					    -gmt true]
			    puts $f2 "test clock-14.[incr n] {parse yymmdd} {"
			    puts $f2 "    [list clock scan $string -format [list $yy $mm $dd] -locale en_US_roman -gmt 1]"
			    puts $f2 "} $scanned"
			}
		    }
		}	
	    }
	}
    }

    puts "testcases14: $n test cases"
}

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
#	output file.
#
#----------------------------------------------------------------------

proc testcases17 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of yyWwwd"
    puts $f2 ""

    set n 0
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \
				    -format "%g W%V $d" \







|



|
|







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
#	output file.
#
#----------------------------------------------------------------------

proc testcases17 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of yyWwwd"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 1971 2000 2001} {
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \
				    -format "%g W%V $d" \
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
#	Test cases for parsing mmdd dates are output.
#
#----------------------------------------------------------------------

proc testcases19 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of mmdd"
    puts $f2 ""

    set n 0
    foreach year {1938 1970 2000 2037} {
	set base [clock scan ${year}0101 -gmt true]
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach mm {%b %B %h %m %Om %N} {
		    foreach dd {%d %Od %e %Oe} {
			set string [clock format $scanned \
					-format "$mm $dd" \
					-locale en_US_roman \
					-gmt true]
			puts $f2 "test clock-19.[incr n] {parse mmdd} {"
			puts $f2 "    [list clock scan $string -format [list $mm $dd] -locale en_US_roman -base $base -gmt 1]"
			puts $f2 "} $scanned"
		    }
		}
	    }
	}
    }

    puts "testcases19: $n test cases"
}








|



|
|















|







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
#	Test cases for parsing mmdd dates are output.
#
#----------------------------------------------------------------------

proc testcases19 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of mmdd"
    puts $f2 ""
    
    set n 0 
    foreach year {1938 1970 2000 2037} {
	set base [clock scan ${year}0101 -gmt true]
	foreach month {01 12} {
	    foreach day {02 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach mm {%b %B %h %m %Om %N} {
		    foreach dd {%d %Od %e %Oe} {
			set string [clock format $scanned \
					-format "$mm $dd" \
					-locale en_US_roman \
					-gmt true]
			puts $f2 "test clock-19.[incr n] {parse mmdd} {"
			puts $f2 "    [list clock scan $string -format [list $mm $dd] -locale en_US_roman -base $base -gmt 1]"
			puts $f2 "} $scanned"
		    }
		}	
	    }
	}
    }

    puts "testcases19: $n test cases"
}

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
#	output file.
#
#----------------------------------------------------------------------

proc testcases22 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of Wwwd"
    puts $f2 ""

    set n 0
    foreach year {1970 1971 2000 2001} {
	set base [clock scan ${year}0104 -gmt true]
	foreach month {03 10} {
	    foreach day {01 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \







|



|
|







960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
#	output file.
#
#----------------------------------------------------------------------

proc testcases22 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of Wwwd"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 1971 2000 2001} {
	set base [clock scan ${year}0104 -gmt true]
	foreach month {03 10} {
	    foreach day {01 31} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach d {%a %A %u %w %Ou %Ow} {
		    set string [clock format $scanned \
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
#	Test cases for parsing naked day of the month are output.
#
#----------------------------------------------------------------------

proc testcases24 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of naked day-of-month"
    puts $f2 ""

    set n 0
    foreach year {1970 2000} {
	foreach month {01 12} {
	    set base [clock scan ${year}${month}01 -gmt true]
	    foreach day {02 28} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach dd {%d %Od %e %Oe} {
		    set string [clock format $scanned \
				    -format "$dd" \
				    -locale en_US_roman \
				    -gmt true]
		    puts $f2 "test clock-24.[incr n] {parse naked day of month} {"
		    puts $f2 "    [list clock scan $string -format $dd -locale en_US_roman -base $base -gmt 1]"
		    puts $f2 "} $scanned"
		}
	    }
	}
    }

    puts "testcases24: $n test cases"
}








|



|
|













|







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
#	Test cases for parsing naked day of the month are output.
#
#----------------------------------------------------------------------

proc testcases24 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of naked day-of-month"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 2000} {
	foreach month {01 12} {
	    set base [clock scan ${year}${month}01 -gmt true]
	    foreach day {02 28} {
		set scanned [clock scan $year$month$day -gmt true]
		foreach dd {%d %Od %e %Oe} {
		    set string [clock format $scanned \
				    -format "$dd" \
				    -locale en_US_roman \
				    -gmt true]
		    puts $f2 "test clock-24.[incr n] {parse naked day of month} {"
		    puts $f2 "    [list clock scan $string -format $dd -locale en_US_roman -base $base -gmt 1]"
		    puts $f2 "} $scanned"
		}	
	    }
	}
    }

    puts "testcases24: $n test cases"
}

1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
#	output file.
#
#----------------------------------------------------------------------

proc testcases26 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of naked day of week"
    puts $f2 ""

    set n 0
    foreach year {1970 2001} {
	foreach week {01 52} {
	    set base [clock scan ${year}W${week}4 \
			  -format %GW%V%u -gmt true]
	    foreach day {1 7} {
		set scanned [clock scan ${year}W${week}${day} \
				 -format %GW%V%u -gmt true]







|



|
|







1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
#	output file.
#
#----------------------------------------------------------------------

proc testcases26 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of naked day of week"
    puts $f2 ""
    
    set n 0 
    foreach year {1970 2001} {
	foreach week {01 52} {
	    set base [clock scan ${year}W${week}4 \
			  -format %GW%V%u -gmt true]
	    foreach day {1 7} {
		set scanned [clock scan ${year}W${week}${day} \
				 -format %GW%V%u -gmt true]
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
#	Writes the tests.
#
#----------------------------------------------------------------------

proc testcases29 { f2 } {

    # Put out a header describing the tests

    puts $f2 ""
    puts $f2 "\# Test parsing of time of day"
    puts $f2 ""

    set n 0
    foreach hour {0 1 11 12 13 23} \
	hampm {12 1 11 12 1 11} \







|







1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
#	Writes the tests.
#
#----------------------------------------------------------------------

proc testcases29 { f2 } {

    # Put out a header describing the tests
    
    puts $f2 ""
    puts $f2 "\# Test parsing of time of day"
    puts $f2 ""

    set n 0
    foreach hour {0 1 11 12 13 23} \
	hampm {12 1 11 12 1 11} \
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
			    puts $f2 "    clock scan {2440588 $hfld:$lminute:$lsecond $afld} \\"
			    puts $f2 "        -gmt true -locale en_US_roman \\"
			    puts $f2 "        -format {%J $hfmt:%OM:%OS $afmt}"
			    puts $f2 "} $time"
			}
		}
	    }

	}
    puts "testcases29: $n test cases"
}

processFile $d







|





1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
			    puts $f2 "    clock scan {2440588 $hfld:$lminute:$lsecond $afld} \\"
			    puts $f2 "        -gmt true -locale en_US_roman \\"
			    puts $f2 "        -format {%J $hfmt:%OM:%OS $afmt}"
			    puts $f2 "} $time"
			}
		}
	    }
	    
	}
    puts "testcases29: $n test cases"
}

processFile $d

Changes to tools/man2help.tcl.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
            if {[string compare $lastSection $section]} {
	    puts $fd "1 $section"
            }
            set lastSection $section
	    set lastTopic {}
	    foreach topic [getTopics $package $section] {
		if {[string compare $lastTopic $topic]} {
		    set id $topics($package,$section,$topic)
		    puts $fd "2 $topic=$id"
		    set lastTopic $topic
		}
	    }
	}
    }
    close $fd







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
            if {[string compare $lastSection $section]} {
	    puts $fd "1 $section"
            }
            set lastSection $section
	    set lastTopic {}
	    foreach topic [getTopics $package $section] {
		if {[string compare $lastTopic $topic]} {
		    set id $topics($package,$section,$topic) 
		    puts $fd "2 $topic=$id"
		    set lastTopic $topic
		}
	    }
	}
    }
    close $fd

Changes to tools/man2help2.tcl.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#				
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    set string [string map [list \
	    "\\"	"\\\\" \
	    "\{"	"\\\{" \
	    "\}"	"\\\}" \
	    "\t"	{\tab } \
	    ''		"\\rdblquote " \
	    ``		"\\ldblquote " \
	    "\xB7"	"\\bullet " \
	    ] $string]

    # Check if this is the beginning of an international character string.
    # If so, look up the sequence in the chars table and substitute the
    # appropriate hex value.

    if {$state(intl)} {
	if {[regexp {^'([^']*)'} $string dummy ch]} {
	    if {[info exists chars($ch)]} {
		regsub {^'[^']*'} $string "\\\\'$chars($ch)" string
	    } else {
		puts stderr "Unknown international character '$ch'"
	    }
	}
	set state(intl) 0
    }

    switch $state(textState) {
	REF {
	    if {$state(inTP) == 0} {
		set string [insertRef $string]
	    }
	}
	SEE {
	    global topics curPkg curSect
	    foreach i [split $string] {
		if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} {
		    continue
		}
		if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} {
		    regsub $i $string [link $i $ref] string







|


















|




|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    set string [string map [list \
	    "\\"	"\\\\" \
	    "\{"	"\\\{" \
	    "\}"	"\\\}" \
	    "\t"	{\tab } \
	    ''		"\\rdblquote " \
	    ``		"\\ldblquote " \
	    "\u00b7"	"\\bullet " \
	    ] $string]

    # Check if this is the beginning of an international character string.
    # If so, look up the sequence in the chars table and substitute the
    # appropriate hex value.

    if {$state(intl)} {
	if {[regexp {^'([^']*)'} $string dummy ch]} {
	    if {[info exists chars($ch)]} {
		regsub {^'[^']*'} $string "\\\\'$chars($ch)" string
	    } else {
		puts stderr "Unknown international character '$ch'"
	    }
	}
	set state(intl) 0
    }

    switch $state(textState) {
	REF { 
	    if {$state(inTP) == 0} {
		set string [insertRef $string]
	    }
	}
	SEE { 
	    global topics curPkg curSect
	    foreach i [split $string] {
		if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} {
		    continue
		}
		if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} {
		    regsub $i $string [link $i $ref] string
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
	    set count [llength $sites]
	    if {$count > 0} {
		set ref $topics([lindex $sites 0])
	    }
	}
    }

    if {($ref != "") && ($ref != $curID)} {
	set string [link $string $ref]
    }
    return $string
}










|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
	    set count [llength $sites]
	    if {$count > 0} {
		set ref $topics([lindex $sites 0])
	    }
	}
    }

    if {($ref != {}) && ($ref != $curID)} {
	set string [link $string $ref]
    }
    return $string
}



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	    }
	    tab
	}
	AS {
	    # next page and previous page
	}
	br {
	    lineBreak
	}
	BS {}
	BE {}
	CE {
	    puts -nonewline $::file "\\f0\\fs20 "
	    set state(noFill) 0
	    set state(breakPending) 0







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	    }
	    tab
	}
	AS {
	    # next page and previous page
	}
	br {
	    lineBreak	
	}
	BS {}
	BE {}
	CE {
	    puts -nonewline $::file "\\f0\\fs20 "
	    set state(noFill) 0
	    set state(breakPending) 0
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	    set state(nestingLevel) 0
	    newPara 0i
	    setTabs {4c 8c 12c}
	    font B
	    set state(noFill) 1
	}
	so {
	    if {$args ne "man.macros"} {
		puts stderr "Unknown macro: .$name [join $args " "]"
	    }
	}
	sp {					;# needs work
	    if {$args eq ""} {
		set count 1
	    } else {
		set count [lindex $args 0]
	    }
	    while {$count > 0} {
		lineBreak
		incr count -1







|




|







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
	    set state(nestingLevel) 0
	    newPara 0i
	    setTabs {4c 8c 12c}
	    font B
	    set state(noFill) 1
	}
	so {
	    if {$args != "man.macros"} {
		puts stderr "Unknown macro: .$name [join $args " "]"
	    }
	}
	sp {					;# needs work
	    if {$args == ""} {
		set count 1
	    } else {
		set count [lindex $args 0]
	    }
	    while {$count > 0} {
		lineBreak
		incr count -1
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

proc font {type} {
    global state
    switch $type {
	P -
	R {
	    endFont
	    if {$state(textState) eq "REF"} {
		set state(textState) INSERT
	    }
	}
	C -
	B {
	    beginFont Code
	    if {$state(textState) eq "INSERT"} {
		set state(textState) REF
	    }
	}
	I {
	    beginFont Emphasis
	}
	S {







|






|







468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

proc font {type} {
    global state
    switch $type {
	P -
	R {
	    endFont
	    if {$state(textState) == "REF"} {
		set state(textState) INSERT
	    }
	}
	C -
	B {
	    beginFont Code
	    if {$state(textState) == "INSERT"} {
		set state(textState) REF
	    }
	}
	I {
	    beginFont Emphasis
	}
	S {
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
#
# Arguments:
# text -		Text to insert.

proc formattedText {text} {
    global chars

    while {$text ne ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr {$index-1}]]
	set c [string index $text [expr {$index+1}]]







|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
#
# Arguments:
# text -		Text to insert.

proc formattedText {text} {
    global chars

    while {$text != ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr {$index-1}]]
	set c [string index $text [expr {$index+1}]]
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
	    textSetup
	    puts -nonewline $file "\\bullet "
	}
	{\(co} {
	    textSetup
	    puts -nonewline $file "\\'a9 "
	}
	{\(mi} {
	    textSetup
	    puts -nonewline $file "-"
	}
	{\(mu} {
	    textSetup
	    puts -nonewline $file "\\'d7 "
	}
	{\(em} - {\(en} {
	    textSetup
	    puts -nonewline $file "-"
	}
	{\(fm} {
	    textSetup
	    puts -nonewline $file "\\'27 "
	}







<
<
<
<




|







705
706
707
708
709
710
711




712
713
714
715
716
717
718
719
720
721
722
723
	    textSetup
	    puts -nonewline $file "\\bullet "
	}
	{\(co} {
	    textSetup
	    puts -nonewline $file "\\'a9 "
	}




	{\(mu} {
	    textSetup
	    puts -nonewline $file "\\'d7 "
	}
	{\(em} {
	    textSetup
	    puts -nonewline $file "-"
	}
	{\(fm} {
	    textSetup
	    puts -nonewline $file "\\'27 "
	}
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774

    set args [join $argList " "]
    if {[llength $argList] < 1} {
	puts stderr "Bad .SH macro: .SH $args"
    }

    # control what the text proc does with text

    switch $args {
	NAME {set state(textState) NAME}
	DESCRIPTION {set state(textState) INSERT}
	INTRODUCTION {set state(textState) INSERT}
	"WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT}
	"SEE ALSO" {set state(textState) SEE}
	KEYWORDS {set state(textState) KEY; return}







|







756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

    set args [join $argList " "]
    if {[llength $argList] < 1} {
	puts stderr "Bad .SH macro: .SH $args"
    }

    # control what the text proc does with text
    
    switch $args {
	NAME {set state(textState) NAME}
	DESCRIPTION {set state(textState) INSERT}
	INTRODUCTION {set state(textState) INSERT}
	"WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT}
	"SEE ALSO" {set state(textState) SEE}
	KEYWORDS {set state(textState) KEY; return}
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
    if {$length == 0} {
	set text {\(bu}
	set indent 5
    } elseif {$length == 1} {
	set indent 5
    }
    if {$text == {\(bu}} {
	set text "\xB7"
    }

    set tab [expr {$indent * 0.1}]i
    newPara $tab -$tab
    set state(sb) 80
    setTabs $tab
    formattedText $text
    tab
}








|


|







816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
    if {$length == 0} {
	set text {\(bu}
	set indent 5
    } elseif {$length == 1} {
	set indent 5
    }
    if {$text == {\(bu}} {
	set text "\u00b7"
    }

    set tab [expr $indent * 0.1]i
    newPara $tab -$tab
    set state(sb) 80
    setTabs $tab
    formattedText $text
    tab
}

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
    }
    incr curID
    set name	[lindex $argList 0]		;# Tcl_UpVar
    set page	[lindex $argList 1]		;# 3
    set curVer	[lindex $argList 2]		;# 7.4
    set curPkg	[lindex $argList 3]		;# Tcl
    set curSect	[lindex $argList 4]		;# {Tcl Library Procedures}

    regsub -all {\\ } $curSect { } curSect	;# Clean up for [incr\ Tcl]

    puts $file "#{\\footnote $curID}"		;# Context string
    puts $file "\${\\footnote $name}"		;# Topic title
    set browse "${curSect}${name}"
    regsub -all {[ _-]} $browse {} browse
    puts $file "+{\\footnote $browse}"		;# Browse sequence







|







881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
    }
    incr curID
    set name	[lindex $argList 0]		;# Tcl_UpVar
    set page	[lindex $argList 1]		;# 3
    set curVer	[lindex $argList 2]		;# 7.4
    set curPkg	[lindex $argList 3]		;# Tcl
    set curSect	[lindex $argList 4]		;# {Tcl Library Procedures}
    
    regsub -all {\\ } $curSect { } curSect	;# Clean up for [incr\ Tcl]

    puts $file "#{\\footnote $curID}"		;# Context string
    puts $file "\${\\footnote $name}"		;# Topic title
    set browse "${curSect}${name}"
    regsub -all {[ _-]} $browse {} browse
    puts $file "+{\\footnote $browse}"		;# Browse sequence
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
# firstState(Indent) -		The new left margin for the first line of a state(paragraph).

proc newPara {leftIndent {firstIndent 0i}} {
    global state file
    if $state(paragraph) {
	puts -nonewline $file "\\line\n"
    }
    if {$leftIndent ne ""} {
	set state(leftIndent) [expr {$state(leftMargin) \
		+ ($state(offset) * $state(nestingLevel)) \
		+ [getTwips $leftIndent]}]
    }
    set state(firstIndent) [getTwips $firstIndent]
    set state(paragraphPending) 1
}







|







946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
# firstState(Indent) -		The new left margin for the first line of a state(paragraph).

proc newPara {leftIndent {firstIndent 0i}} {
    global state file
    if $state(paragraph) {
	puts -nonewline $file "\\line\n"
    }
    if {$leftIndent != ""} {
	set state(leftIndent) [expr {$state(leftMargin) \
		+ ($state(offset) * $state(nestingLevel)) \
		+ [getTwips $leftIndent]}]
    }
    set state(firstIndent) [getTwips $firstIndent]
    set state(paragraphPending) 1
}
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
# the number of indentations that affect things like .PP.
#
# Arguments:
# None.

proc decrNestingLevel {} {
    global state

    if {$state(nestingLevel) == 0} {
	puts stderr "Nesting level decremented below 0"
    } else {
	incr state(nestingLevel) -1
    }
}







|






1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
# the number of indentations that affect things like .PP.
#
# Arguments:
# None.

proc decrNestingLevel {} {
    global state
    
    if {$state(nestingLevel) == 0} {
	puts stderr "Nesting level decremented below 0"
    } else {
	incr state(nestingLevel) -1
    }
}

Changes to tools/man2html.tcl.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
proc sarray {file args} {
    set file [open $file w]
    foreach a $args {
	upvar $a array
	if {![array exists array]} {
	    puts "sarray: \"$a\" isn't an array"
	    break
	}

	foreach name [lsort [array names array]] {
	    regsub -all " " $name "\\ " name1
	    puts $file "set ${a}($name1) \{$array($name)\}"
	}
    }
    close $file
}







|
|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
proc sarray {file args} {
    set file [open $file w]
    foreach a $args {
	upvar $a array
	if {![array exists array]} {
	    puts "sarray: \"$a\" isn't an array"
	    break
	}	
    
	foreach name [lsort [array names array]] {
	    regsub -all " " $name "\\ " name1
	    puts $file "set ${a}($name1) \{$array($name)\}"
	}
    }
    close $file
}
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

    set footer [footer $packages]

    # make the hyperlink arrays and contents.html for all packages

    foreach package $packages {
	file mkdir $html_dir/$package

	# build hyperlink database arrays: NAME_file and KEY_file
	#
	puts "\nScanning man pages in $tcl_dir/$package/doc..."
	uplevel \#0 [list source $homeDir/man2html1.tcl]

	doDir $tcl_dir/$package/doc

	# clean up the NAME_file and KEY_file database arrays
	#
	catch {unset KEY_file()}
	foreach name [lsort [array names NAME_file]] {
	    set file_name $NAME_file($name)







|




|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

    set footer [footer $packages]

    # make the hyperlink arrays and contents.html for all packages

    foreach package $packages {
	file mkdir $html_dir/$package
    
	# build hyperlink database arrays: NAME_file and KEY_file
	#
	puts "\nScanning man pages in $tcl_dir/$package/doc..."
	uplevel \#0 [list source $homeDir/man2html1.tcl]
    
	doDir $tcl_dir/$package/doc

	# clean up the NAME_file and KEY_file database arrays
	#
	catch {unset KEY_file()}
	foreach name [lsort [array names NAME_file]] {
	    set file_name $NAME_file($name)

Changes to tools/man2html1.tcl.

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
# man2html1.tcl --
#
# This file defines procedures that are used during the first pass of the
# man page to html conversion process. It is sourced by h.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# curFile -	tail of current man page.
#
# file -	file pointer; for both xref.tcl and contents.html
#
# NAME_file -	array indexed by NAME and containing file names used
#		for hyperlinks.
#
# KEY_file -	array indexed by KEYWORD and containing file names used
#		for hyperlinks.
#
# lib -		contains package name. Used to label section in contents.html
#
# inDT -	in dictionary term.


# text --
#
# This procedure adds entries to the hypertext arrays NAME_file
# and KEY_file.
#
# DT: might do this: if first word of $dt matches $name and [llength $name==1]
# 	and [llength $dt > 1], then add to NAME_file.
#
# Arguments:
# string -		Text to index.

proc text string {
    global state curFile NAME_file KEY_file inDT











|












|








|







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
# man2html1.tcl --
#
# This file defines procedures that are used during the first pass of the
# man page to html conversion process. It is sourced by h.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#				
# curFile -	tail of current man page.
#
# file -	file pointer; for both xref.tcl and contents.html
#
# NAME_file -	array indexed by NAME and containing file names used
#		for hyperlinks.
#
# KEY_file -	array indexed by KEYWORD and containing file names used
#		for hyperlinks.
#
# lib -		contains package name. Used to label section in contents.html
#
# inDT -	in dictionary term. 


# text --
#
# This procedure adds entries to the hypertext arrays NAME_file
# and KEY_file.
#
# DT: might do this: if first word of $dt matches $name and [llength $name==1]
# 	and [llength $dt > 1], then add to NAME_file. 
#
# Arguments:
# string -		Text to index.

proc text string {
    global state curFile NAME_file KEY_file inDT

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
		    }
		}
		DESCRIPTION {set state DT}
		INTRODUCTION {set state DT}
		KEYWORDS {set state KEY}
		default {set state OFF}
	    }

	}
	TP {
	    global inDT
	    set inDT 1
	}
	TH {
	    global lib state inDT







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
		    }
		}
		DESCRIPTION {set state DT}
		INTRODUCTION {set state DT}
		KEYWORDS {set state KEY}
		default {set state OFF}
	    }
		
	}
	TP {
	    global inDT
	    set inDT 1
	}
	TH {
	    global lib state inDT
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    global inDT
    set inDT 0
}


# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass.
#
# Arguments:
# None.

proc initGlobals {} {}
proc tab {} {}
proc font type {}







|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    global inDT
    set inDT 0
}


# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass. 
#
# Arguments:
# None.

proc initGlobals {} {}
proc tab {} {}
proc font type {}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# file -		name of the contents file.
# packageName -		string used in the title and sub-heads of the HTML
#			page. Normally name of the package without version
#			numbers.

proc doContents {file packageName} {
    global footer

    set file [open $file w]

    puts $file "<HTML><HEAD><TITLE>$packageName Manual</TITLE></HEAD><BODY>"
    puts $file "<H3>$packageName</H3>"
    doListing $file "*.1"

    puts $file "<HR><H3>$packageName Commands</H3>"
    doListing $file "*.n"

    puts $file "<HR><H3>$packageName Library</H3>"
    doListing $file "*.3"

    puts $file $footer
    puts $file "</BODY></HTML>"
    close $file
}


# do --
#
# This is the toplevel procedure that searches a man page
# for hypertext links.  It builds a data base consisting of
# two arrays: NAME_file and KEY file. It runs the man2tcl
# program to turn the man page into a script, then it evals
# that script.
#
# Arguments:
# fileName -		Name of the file to scan.

proc do fileName {
    global curFile







|

|




















|
|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# file -		name of the contents file.
# packageName -		string used in the title and sub-heads of the HTML
#			page. Normally name of the package without version
#			numbers.

proc doContents {file packageName} {
    global footer
    
    set file [open $file w]
    
    puts $file "<HTML><HEAD><TITLE>$packageName Manual</TITLE></HEAD><BODY>"
    puts $file "<H3>$packageName</H3>"
    doListing $file "*.1"

    puts $file "<HR><H3>$packageName Commands</H3>"
    doListing $file "*.n"

    puts $file "<HR><H3>$packageName Library</H3>"
    doListing $file "*.3"

    puts $file $footer
    puts $file "</BODY></HTML>"
    close $file
}


# do --
#
# This is the toplevel procedure that searches a man page
# for hypertext links.  It builds a data base consisting of
# two arrays: NAME_file and KEY file. It runs the man2tcl 
# program to turn the man page into a script, then it evals 
# that script.
#
# Arguments:
# fileName -		Name of the file to scan.

proc do fileName {
    global curFile

Changes to tools/man2html2.tcl.

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# string -		Text to output in the paragraph.

proc text string {
    global file textState inDT charCnt inTable

    set pos [string first "\t" $string]
    if {$pos >= 0} {
    	text [string range $string 0 [expr {$pos-1}]]
    	tab
    	text [string range $string [expr {$pos+1}] end]
	return
    }
    if {$inTable} {
	if {$inTable == 1} {
	    puts -nonewline $file <TR>
	    set inTable 2
	}







|

|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# string -		Text to output in the paragraph.

proc text string {
    global file textState inDT charCnt inTable

    set pos [string first "\t" $string]
    if {$pos >= 0} {
    	text [string range $string 0 [expr $pos-1]]
    	tab
    	text [string range $string [expr $pos+1] end]
	return
    }
    if {$inTable} {
	if {$inTable == 1} {
	    puts -nonewline $file <TR>
	    set inTable 2
	}
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
#	puts "formattedText: $text"
    while {$text ne ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr {$index-1}]]
	set c [string index $text [expr {$index+1}]]
	switch -- $c {
	    f {
		font [string index $text [expr {$index+2}]]
		set text [string range $text [expr {$index+3}] end]
	    }
	    e {
		text \\
		set text [string range $text [expr {$index+2}] end]
	    }
	    - {
		dash
		set text [string range $text [expr {$index+2}] end]
	    }
	    | {
		set text [string range $text [expr {$index+2}] end]
	    }
	    default {
		puts stderr "Unknown sequence: \\$c"
		set text [string range $text [expr {$index+2}] end]
	    }
	}
    }
}

##############################################################################
# dash --







|
|


|
|



|



|


|



|







467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
#	puts "formattedText: $text"
    while {$text ne ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr $index-1]]
	set c [string index $text [expr $index+1]]
	switch -- $c {
	    f {
		font [string index $text [expr $index+2]]
		set text [string range $text [expr $index+3] end]
	    }
	    e {
		text \\
		set text [string range $text [expr $index+2] end]
	    }
	    - {
		dash
		set text [string range $text [expr $index+2] end]
	    }
	    | {
		set text [string range $text [expr $index+2] end]
	    }
	    default {
		puts stderr "Unknown sequence: \\$c"
		set text [string range $text [expr $index+2] end]
	    }
	}
    }
}

##############################################################################
# dash --
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
# Arguments:
# None.

proc tab {} {
    global inPRE charCnt tabString file
#	? charCnt
    if {$inPRE == 1} {
	set pos [expr {$charCnt % [string length $tabString]}]
	set spaces [string first "1" [string range $tabString $pos end] ]
	text [format "%*s" [incr spaces] " "]
    } else {
#	puts "tab: found tab outside of <PRE> block"
    }
}








|







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
# Arguments:
# None.

proc tab {} {
    global inPRE charCnt tabString file
#	? charCnt
    if {$inPRE == 1} {
	set pos [expr $charCnt % [string length $tabString] ]
	set spaces [string first "1" [string range $tabString $pos end] ]
	text [format "%*s" [incr spaces] " "]
    } else {
#	puts "tab: found tab outside of <PRE> block"
    }
}

Changes to tools/mkdepend.tcl.

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
#==============================================================================
#
# mkdepend : generate dependency information from C/C++ files
#
# Copyright (c) 1998, Nat Pryce
#
# Permission is hereby granted, without written agreement and without
# license or royalty fees, to use, copy, modify, and distribute this
# software and its documentation for any purpose, provided that the
# above copyright notice and the following two paragraphs appear in
# all copies of this software.
#
# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.
#
# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
# BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE  MAINTENANCE, SUPPORT,
# UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#==============================================================================
#
# Modified heavily by David Gravereaux <[email protected]> about 9/17/2006.
# Original can be found @
#	http://web.archive.org/web/20070616205924/http://www.doc.ic.ac.uk/~np2/software/mkdepend.html
#==============================================================================

array set mode_data {}
set mode_data(vc32) {cl -nologo -E}

set source_extensions [list .c .cpp .cxx .cc]












|
|
|


|
|
|





|







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
#==============================================================================
#
# mkdepend : generate dependency information from C/C++ files
#
# Copyright (c) 1998, Nat Pryce
#
# Permission is hereby granted, without written agreement and without
# license or royalty fees, to use, copy, modify, and distribute this
# software and its documentation for any purpose, provided that the
# above copyright notice and the following two paragraphs appear in
# all copies of this software.
#
# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 
# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF 
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED 
# OF THE POSSIBILITY OF SUCH DAMAGE.
#
# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
# PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 
# BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE  MAINTENANCE, SUPPORT,
# UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#==============================================================================
#
# Modified heavily by David Gravereaux <[email protected]> about 9/17/2006.
# Original can be found @ 
#	http://web.archive.org/web/20070616205924/http://www.doc.ic.ac.uk/~np2/software/mkdepend.html
#==============================================================================

array set mode_data {}
set mode_data(vc32) {cl -nologo -E}

set source_extensions [list .c .cpp .cxx .cc]
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
# Results:
#	Raw dependency list pairs.

proc readDepends {chan} {
    set line ""
    array set depends {}

    while {[gets $chan line] >= 0} {
        if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} {
	    set fname [file normalize $fname]
            if {![info exists target]} {
		# this is ourself
		set target $fname
		puts stderr "processing [file tail $fname]"
            } else {
		# don't include ourselves as a dependency of ourself.
		if {![string compare $fname $target]} {continue}
		# store in an array so multiple occurrences are not counted.
                set depends($target|$fname) ""
            }
        }
    }

    set result {}
    foreach n [array names depends] {







|









|







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
# Results:
#	Raw dependency list pairs.

proc readDepends {chan} {
    set line ""
    array set depends {}

    while {[gets $chan line] != -1} {
        if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} {
	    set fname [file normalize $fname]
            if {![info exists target]} {
		# this is ourself
		set target $fname
		puts stderr "processing [file tail $fname]"
            } else {
		# don't include ourselves as a dependency of ourself.
		if {![string compare $fname $target]} {continue}
		# store in an array so multiple occurances are not counted.
                set depends($target|$fname) ""
            }
        }
    }

    set result {}
    foreach n [array names depends] {

Changes to tools/regexpTestLib.tcl.

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
    set fileId [open $inFileName r]

    set i 0
    while {[gets $fileId line] >= 0} {

	set len [string length $line]

	if {($len > 0) && ([string index $line [expr {$len - 1}]] == "\\")} {
	    if {[info exists lineArray(c$i)] == 0} {
		set lineArray(c$i) 1
	    } else {
		incr lineArray(c$i)
	    }
	    set line [string range $line 0 [expr {$len - 2}]]
	    append lineArray($i) $line
	    continue
	}
	if {[info exists lineArray(c$i)] == 0} {
	    set lineArray(c$i) 1
	} else {
	    incr lineArray(c$i)
	}
	append lineArray($i) $line
	incr i
    }

    close $fileId
    return $i
}

#
# strings with embedded @'s are truncated
# unpreceeded @'s are replaced by {}
#
proc removeAts {ls} {
    set len [llength $ls]
    set newLs {}
    foreach item $ls {
	regsub @.* $item "" newItem
	lappend newLs $newItem
    }







|





|



















|







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
    set fileId [open $inFileName r]

    set i 0
    while {[gets $fileId line] >= 0} {

	set len [string length $line]

	if {($len > 0) && ([string index $line [expr $len - 1]] == "\\")} {
	    if {[info exists lineArray(c$i)] == 0} {
		set lineArray(c$i) 1
	    } else {
		incr lineArray(c$i)
	    }
	    set line [string range $line 0 [expr $len - 2]]
	    append lineArray($i) $line
	    continue
	}
	if {[info exists lineArray(c$i)] == 0} {
	    set lineArray(c$i) 1
	} else {
	    incr lineArray(c$i)
	}
	append lineArray($i) $line
	incr i
    }

    close $fileId
    return $i
}

#
# strings with embedded @'s are truncated
# unpreceeded @'s are replaced by {}
# 
proc removeAts {ls} {
    set len [llength $ls]
    set newLs {}
    foreach item $ls {
	regsub @.* $item "" newItem
	lappend newLs $newItem
    }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    return "$errMsg $code"
}

proc writeOutputFile {numLines fcn} {
    global outFileName
    global lineArray

    # open output file and write file header info to it.

    set fileId [open $outFileName w]

    puts $fileId "# Commands covered:  $fcn"
    puts $fileId "#"
    puts $fileId "# This Tcl-generated file contains tests for the $fcn tcl command."
    puts $fileId "# Sourcing this file into Tcl runs the tests and generates output for"







|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    return "$errMsg $code"
}

proc writeOutputFile {numLines fcn} {
    global outFileName
    global lineArray

    # open output file and write file header info to it. 

    set fileId [open $outFileName w]

    puts $fileId "# Commands covered:  $fcn"
    puts $fileId "#"
    puts $fileId "# This Tcl-generated file contains tests for the $fcn tcl command."
    puts $fileId "# Sourcing this file into Tcl runs the tests and generates output for"
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

	# copy comment string to output file and continue

	if {[string index $currentLine 0] == "#"} {
	    puts $fileId $currentLine
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue
	}

	set len [llength $currentLine]

	# copy empty string to output file and continue

	if {$len == 0} {
	    puts $fileId "\n"
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue
	}
	if {($len < 3)} {
	    puts "warning: test is too short --\n\t$currentLine"
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue
	}







|










|







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

	# copy comment string to output file and continue

	if {[string index $currentLine 0] == "#"} {
	    puts $fileId $currentLine
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue	    
	}

	set len [llength $currentLine]

	# copy empty string to output file and continue

	if {$len == 0} {
	    puts $fileId "\n"
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue	    
	}
	if {($len < 3)} {
	    puts "warning: test is too short --\n\t$currentLine"
	    incr srcLineNum $lineArray(c$lineNum)
	    incr lineNum
	    continue
	}
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
	}
	set str [lindex $currentLine 2]
    }
    set flags [removeFlags $flags]

    # find the test result

    set numVars [expr {$len - 3}]
    set vars {}
    set vals {}
    set result 0
    set v 0

    if {[regsub {\*} "$flags" "" newFlags] == 1} {
	# an error is expected

	if {[string compare $str "EMPTY"] == 0} {
	    # empty regexp is not an error
	    # skip this test

	    return "\# skipping the empty-re test from line $srcLineNum\n"
	}
	set flags $newFlags
	set result "\{1 \{[convertErrCode $str]\}\}"
    } elseif {$numVars > 0} {
	# at least 1 match is made

	if {[regexp {s} $flags] == 1} {
	    set result "\{0 1\}"
	} else {
	    while {$v < $numVars} {
		append vars " var($v)"
		append vals " \$var($v)"
		incr v
	    }
	    set tmp [removeAts [lrange $currentLine 3 $len]]
	    set result "\{0 \{1 $tmp\}\}"
	    if {$noBraces} {
		set result "\[subst $result\]"
	    }
	}
    } else {
	# no match is made

	set result "\{0 0\}"
    }

    # set up the test and write it to the output file

    set cmd [prepareCmd $flags $re $str $vars $noBraces]
    if {$cmd == -1} {
	return "\# skipping test with metasyntax from line $srcLineNum\n"
    }

    set test "test regexp-1.$srcLineNum \{converted from line $srcLineNum\} \{\n"
    append test "\tcatch {unset var}\n"
    append test "\tlist \[catch \{\n"
    append test "\t\tset match \[$cmd\]\n"
    append test "\t\tlist \$match $vals\n"
    append test "\t\} msg\] \$msg\n"
    append test "\} $result\n"
    return $test
}








|




|


|



|






|
















|







|




|
|
|
|
|



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
	}
	set str [lindex $currentLine 2]
    }
    set flags [removeFlags $flags]

    # find the test result

    set numVars [expr $len - 3]
    set vars {}
    set vals {}
    set result 0
    set v 0
    
    if {[regsub {\*} "$flags" "" newFlags] == 1} {
	# an error is expected
	
	if {[string compare $str "EMPTY"] == 0} {
	    # empty regexp is not an error
	    # skip this test
	    
	    return "\# skipping the empty-re test from line $srcLineNum\n"
	}
	set flags $newFlags
	set result "\{1 \{[convertErrCode $str]\}\}"
    } elseif {$numVars > 0} {
	# at least 1 match is made
	
	if {[regexp {s} $flags] == 1} {
	    set result "\{0 1\}"
	} else {
	    while {$v < $numVars} {
		append vars " var($v)"
		append vals " \$var($v)"
		incr v
	    }
	    set tmp [removeAts [lrange $currentLine 3 $len]]
	    set result "\{0 \{1 $tmp\}\}"
	    if {$noBraces} {
		set result "\[subst $result\]"
	    }
	}
    } else {
	# no match is made
	
	set result "\{0 0\}"
    }

    # set up the test and write it to the output file

    set cmd [prepareCmd $flags $re $str $vars $noBraces]
    if {$cmd == -1} {
	return "\# skipping test with metasyntax from line $srcLineNum\n"	    
    }

    set test "test regexp-1.$srcLineNum \{converted from line $srcLineNum\} \{\n"
    append test "\tcatch {unset var}\n"
    append test "\tlist \[catch \{ \n"
    append test "\t\tset match \[$cmd\] \n"
    append test "\t\tlist \$match $vals \n"
    append test "\t\} msg\] \$msg \n"
    append test "\} $result \n"
    return $test
}

Changes to tools/tclZIC.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#----------------------------------------------------------------------
#
# tclZIC.tcl --
#
#	Take the time zone data source files from Arthur Olson's
#	repository at https://www.iana.org/time-zones, and prepare time zone
#	information files for Tcl.
#
# Usage:
#	tclsh tclZIC.tcl inputDir outputDir
#
# Parameters:
#	inputDir - Directory (e.g., tzdata2022a) where Olson's source
#		   files are to be found.
#	outputDir - Directory (e.g., ../library/tzdata) where
#		    the time zone information files are to be placed.
#
# Results:
#	May produce error messages on the standard error.  An exit
#	code of zero denotes success; any other exit code is failure.





|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#----------------------------------------------------------------------
#
# tclZIC.tcl --
#
#	Take the time zone data source files from Arthur Olson's
#	repository at elsie.nci.nih.gov, and prepare time zone
#	information files for Tcl.
#
# Usage:
#	tclsh tclZIC.tcl inputDir outputDir
#
# Parameters:
#	inputDir - Directory (e.g., tzdata2003e) where Olson's source
#		   files are to be found.
#	outputDir - Directory (e.g., ../library/tzdata) where
#		    the time zone information files are to be placed.
#
# Results:
#	May produce error messages on the standard error.  An exit
#	code of zero denotes success; any other exit code is failure.
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	  ([<>]=)
	  # field 4 - number
	  ([[:digit:]]+)
	|
	  # third possibility - lastWeekday - field 5
	  last([[:alpha:]]+)
	)$
    } $on -> dom1 wday2 dir2 num2 wday3]} {
	error "can't parse ON field \"$on\""
    }
    if {$dom1 ne ""} {
	return [list onDayOfMonth $dom1]
    } elseif {$wday2 ne ""} {
	set wday2 [lookupDayOfWeek $wday2]
	return [list onWeekdayInMonth $wday2 $dir2 $num2]







|







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	  ([<>]=)
	  # field 4 - number
	  ([[:digit:]]+)
	|
	  # third possibility - lastWeekday - field 5
	  last([[:alpha:]]+)
	)$
    } $on -> dom1 wday2 dir2 num2 wday3]} then {
	error "can't parse ON field \"$on\""
    }
    if {$dom1 ne ""} {
	return [list onDayOfMonth $dom1]
    } elseif {$wday2 ne ""} {
	set wday2 [lookupDayOfWeek $wday2]
	return [list onWeekdayInMonth $wday2 $dir2 $num2]
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
	    (?:
		:([[:digit:]]{2})	# field 3 - second
	    )?
	)?
	(?:
	    ([wsugz])			# field 4 - type indicator
	)?
    } $tod -> hour minute second ind]} {
	puts stderr "$fileName:$lno:can't parse time field \"$tod\""
	incr errorCount
    }
    scan $hour %d hour
    if {$minute ne ""} {
	scan $minute %d minute
    } else {







|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
	    (?:
		:([[:digit:]]{2})	# field 3 - second
	    )?
	)?
	(?:
	    ([wsugz])			# field 4 - type indicator
	)?
    } $tod -> hour minute second ind]} then {
	puts stderr "$fileName:$lno:can't parse time field \"$tod\""
	incr errorCount
    }
    scan $hour %d hour
    if {$minute ne ""} {
	scan $minute %d minute
    } else {
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	([[:digit:]]{1,2})		# field 2 - hour
	(?:
	    :([[:digit:]]{2})		# field 3 - minute
	    (?:
		:([[:digit:]]{2})	# field 4 - second
	    )?
	)?
    } $offset -> signum hour minute second]} {
	puts stderr "$fileName:$lno:can't parse offset time \"$offset\""
	incr errorCount
    }
    append signum 1
    scan $hour %d hour
    if {$minute ne ""} {
	scan $minute %d minute







|







552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	([[:digit:]]{1,2})		# field 2 - hour
	(?:
	    :([[:digit:]]{2})		# field 3 - minute
	    (?:
		:([[:digit:]]{2})	# field 4 - second
	    )?
	)?
    } $offset -> signum hour minute second]} then {
	puts stderr "$fileName:$lno:can't parse offset time \"$offset\""
	incr errorCount
    }
    append signum 1
    scan $hour %d hour
    if {$minute ne ""} {
	scan $minute %d minute
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
		    yearType monthIn daySpecOn timeAt save letter

	    # Test if the rule is in effect.

	    if {
		$earliestSecs > $startSecs &&
		($until eq "" || $earliestSecs < $untilSecs)
	    } {
		# Test if the initial transition has been done.
		# If not, do it now.

		if {!$didTransitionIn && $earliestSecs > $origStartSecs} {
		    set nm [convertNamePattern $namePattern $prevLetter]
		    lappend points \
			    $origStartSecs \







|







934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
		    yearType monthIn daySpecOn timeAt save letter

	    # Test if the rule is in effect.

	    if {
		$earliestSecs > $startSecs &&
		($until eq "" || $earliestSecs < $untilSecs)
	    } then {
		# Test if the initial transition has been done.
		# If not, do it now.

		if {!$didTransitionIn && $earliestSecs > $origStartSecs} {
		    set nm [convertNamePattern $namePattern $prevLetter]
		    lappend points \
			    $origStartSecs \
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997

	# Advance to the next year

	incr year
	set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		[dict create era CE year $year month 1 dayOfMonth 1] 2361222]
	set startSecs [expr {
	    [dict get $date julianDay] * wide(86400) - 210866803200
		- $stdGMTOffset - $DSTOffset
	}]

	# Get rules in effect in the new year.

	lassign [divideRules $ruleSet $year] currentRules nSunsetRules
    }







|







983
984
985
986
987
988
989
990
991
992
993
994
995
996
997

	# Advance to the next year

	incr year
	set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		[dict create era CE year $year month 1 dayOfMonth 1] 2361222]
	set startSecs [expr {
	    [dict get $date julianDay] * wide(86400) - 210866803200 
		- $stdGMTOffset - $DSTOffset
	}]

	# Get rules in effect in the new year.

	lassign [divideRules $ruleSet $year] currentRules nSunsetRules
    }

Changes to tools/tcltk-man2html.tcl.

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
		     {\&}	"\t" \
		     {\%}	{} \
		     "\\\n"	"\n" \
		     {\(+-}	"&#177;" \
		     {\(co}	"&copy;" \
		     {\(em}	"&#8212;" \
		     {\(fm}	"&#8242;" \
		     {\(mc}	"&#181;" \
		     {\(mu}	"&#215;" \
		     {\(->}	"<font size=\"+1\">&#8594;</font>" \
		     {\fP}	{\fR} \
		     {\.}	. \
		     {\(bu}	"&#8226;" \
		    ]
    lappend charmap {\o'o^'} {&ocirc;} ; # o-circumflex in re_syntax.n







<







347
348
349
350
351
352
353

354
355
356
357
358
359
360
		     {\&}	"\t" \
		     {\%}	{} \
		     "\\\n"	"\n" \
		     {\(+-}	"&#177;" \
		     {\(co}	"&copy;" \
		     {\(em}	"&#8212;" \
		     {\(fm}	"&#8242;" \

		     {\(mu}	"&#215;" \
		     {\(->}	"<font size=\"+1\">&#8594;</font>" \
		     {\fP}	{\fR} \
		     {\.}	. \
		     {\(bu}	"&#8226;" \
		    ]
    lappend charmap {\o'o^'} {&ocirc;} ; # o-circumflex in re_syntax.n
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
	default {
	    manerror "unrecognized format directive: $line"
	}
    }
}
##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
    set merge {}
    set re1 {^Copyright +(?:\(c\)|\\\(co|&copy;) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
    set re2 {^(\d+) +(?:by +)?(\w.*)$}         ;# date who
    set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$}   ;# from to who
    set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
    foreach copyright [concat $l1 $l2] {







|







1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
	default {
	    manerror "unrecognized format directive: $line"
	}
    }
}
##
## merge copyright listings
## 
proc merge-copyrights {l1 l2} {
    set merge {}
    set re1 {^Copyright +(?:\(c\)|\\\(co|&copy;) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
    set re2 {^(\d+) +(?:by +)?(\w.*)$}         ;# date who
    set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$}   ;# from to who
    set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
    foreach copyright [concat $l1 $l2] {

Changes to tools/uniClass.tcl.

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
#	in order for the class ranges to match.
#

proc emitRange {first last} {
    global ranges numranges chars numchars extchars extranges

    if {$first < ($last-1)} {
	if {!$extranges && ($first) > 0xFFFF} {
	    set extranges 1
	    set numranges 0
	    set ranges [string trimright $ranges " \n\r\t,"]
	    append ranges "\n#if CHRBITS > 16\n    ,"
	}
	append ranges [format "{0x%X, 0x%X}, " \
		$first $last]
	if {[incr numranges] % 4 == 0} {
	    set ranges [string trimright $ranges]
	    append ranges "\n    "
	}
    } else {
	if {!$extchars && ($first) > 0xFFFF} {
	    set extchars 1
	    set numchars 0
	    set chars [string trimright $chars " \n\r\t,"]
	    append chars "\n#if CHRBITS > 16\n    ,"
	}
	append chars [format "0x%X, " $first]
	incr numchars
	if {$numchars % 9 == 0} {
	    set chars [string trimright $chars]
	    append chars "\n    "
	}
	if {$first != $last} {
	    append chars [format "0x%X, " $last]
	    incr numchars
	    if {$numchars % 9 == 0} {
		append chars "\n    "
	    }
	}
    }
}

proc genTable {type} {
    global first last ranges numranges chars numchars extchars extranges
    set first -2
    set last -2

    set ranges "    "
    set numranges 0
    set chars "    "
    set numchars 0
    set extchars 0
    set extranges 0

    for {set i 0} {$i <= 0x10FFFF} {incr i} {
	if {$i == 0xD800} {
	    # Skip surrogates
	    set i 0xE000
	}
	if {[string is $type [format %c $i]]} {
	    if {$i == ($last + 1)} {
		set last $i
	    } else {
		if {$first >= 0} {
		    emitRange $first $last
		}







|





|






|





|






|




















|
|
|
|
|







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
#	in order for the class ranges to match.
#

proc emitRange {first last} {
    global ranges numranges chars numchars extchars extranges

    if {$first < ($last-1)} {
	if {!$extranges && ($first) > 0xffff} {
	    set extranges 1
	    set numranges 0
	    set ranges [string trimright $ranges " \n\r\t,"]
	    append ranges "\n#if CHRBITS > 16\n    ,"
	}
	append ranges [format "{0x%x, 0x%x}, " \
		$first $last]
	if {[incr numranges] % 4 == 0} {
	    set ranges [string trimright $ranges]
	    append ranges "\n    "
	}
    } else {
	if {!$extchars && ($first) > 0xffff} {
	    set extchars 1
	    set numchars 0
	    set chars [string trimright $chars " \n\r\t,"]
	    append chars "\n#if CHRBITS > 16\n    ,"
	}
	append chars [format "0x%x, " $first]
	incr numchars
	if {$numchars % 9 == 0} {
	    set chars [string trimright $chars]
	    append chars "\n    "
	}
	if {$first != $last} {
	    append chars [format "0x%x, " $last]
	    incr numchars
	    if {$numchars % 9 == 0} {
		append chars "\n    "
	    }
	}
    }
}

proc genTable {type} {
    global first last ranges numranges chars numchars extchars extranges
    set first -2
    set last -2

    set ranges "    "
    set numranges 0
    set chars "    "
    set numchars 0
    set extchars 0
    set extranges 0

    for {set i 0} {$i <= 0x10ffff} {incr i} {
    if {$i == 0xd800} {
	# Skip surrogates
	set i 0xe000
    }
	if {[string is $type [format %c $i]]} {
	    if {$i == ($last + 1)} {
		set last $i
	    } else {
		if {$first >= 0} {
		    emitRange $first $last
		}

Changes to tools/uniParse.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# uniParse.tcl --
#
#	This program parses the UnicodeData file and generates the
#	corresponding tclUniData.c file with compressed character
#	data tables.  The input to this program should be the latest
#	UnicodeData file from:
#	    ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
#
# Copyright (c) 1998-1999 Scriptics Corporation.
# All rights reserved.


namespace eval uni {
    set shift 5;		# number of bits of data within a page
				# This value can be adjusted to find the
				# best split to minimize table size








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# uniParse.tcl --
#
#	This program parses the UnicodeData file and generates the
#	corresponding tclUniData.c file with compressed character
#	data tables.  The input to this program should be the latest
#	UnicodeData file from:
#	    ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.


namespace eval uni {
    set shift 5;		# number of bits of data within a page
				# This value can be adjusted to find the
				# best split to minimize table size
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
    return [list $categoryIndex $toupper $tolower $totitle]
}

proc uni::getGroup {value} {
    variable groups

    set gIndex [lsearch -exact $groups $value]
    if {$gIndex < 0} {
	set gIndex [llength $groups]
	lappend groups $value
    }
    return $gIndex
}

proc uni::addPage {info} {
    variable pMap
    variable pages
    variable shift

    set pIndex [lsearch -exact $pages $info]
    if {$pIndex < 0} {
	set pIndex [llength $pages]
	lappend pages $info
    }
    lappend pMap [expr {$pIndex << $shift}]
    return
}








|












|







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
    return [list $categoryIndex $toupper $tolower $totitle]
}

proc uni::getGroup {value} {
    variable groups

    set gIndex [lsearch -exact $groups $value]
    if {$gIndex == -1} {
	set gIndex [llength $groups]
	lappend groups $value
    }
    return $gIndex
}

proc uni::addPage {info} {
    variable pMap
    variable pages
    variable shift

    set pIndex [lsearch -exact $pages $info]
    if {$pIndex == -1} {
	set pIndex [llength $pages]
	lappend pages $info
    }
    lappend pMap [expr {$pIndex << $shift}]
    return
}

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	    set line [format %X [expr {($next-1)|$mask}]]
	    append line ";;Cn;0;ON;;;;;N;;;;;\n"
	}

	set items [split $line \;]

	scan [lindex $items 0] %x index
	if {$index > 0x3FFFF} then {
	    # Ignore characters > plane 3
	    continue
	}
	set index [format %d $index]

	set gIndex [getGroup [getValue $items $index]]

	# Since the input table omits unassigned characters, these will







|
|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	    set line [format %X [expr {($next-1)|$mask}]]
	    append line ";;Cn;0;ON;;;;;N;;;;;\n"
	}

	set items [split $line \;]

	scan [lindex $items 0] %x index
	if {$index > 0x2ffff} then {
	    # Ignore non-BMP characters, as long as Tcl doesn't support them
	    continue
	}
	set index [format %d $index]

	set gIndex [getGroup [getValue $items $index]]

	# Since the input table omits unassigned characters, these will
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

    buildTables $data
    puts "X = [llength $pMap]  Y= [llength $pages]  A= [llength $groups]"
    set size [expr {[llength $pMap]*2 + ([llength $pages]<<$shift)}]
    puts "shift = $shift, space = $size"

    set f [open [file join [lindex $argv 1] tclUniData.c] w]
    fconfigure $f -translation lf -encoding utf-8
    puts $f "/*
 * tclUniData.c --
 *
 *	Declarations of Unicode character information tables.  This file is
 *	automatically generated by the tools/uniParse.tcl script.  Do not
 *	modify this file by hand.
 *
 * Copyright (c) 1998 Scriptics Corporation.
 * All rights reserved.
 */

/*
 * A 16-bit Unicode character is split into two parts in order to index
 * into the following tables.  The lower OFFSET_BITS comprise an offset
 * into a page of characters.  The upper bits comprise the page number.







|







|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

    buildTables $data
    puts "X = [llength $pMap]  Y= [llength $pages]  A= [llength $groups]"
    set size [expr {[llength $pMap]*2 + ([llength $pages]<<$shift)}]
    puts "shift = $shift, space = $size"

    set f [open [file join [lindex $argv 1] tclUniData.c] w]
    fconfigure $f -translation lf
    puts $f "/*
 * tclUniData.c --
 *
 *	Declarations of Unicode character information tables.  This file is
 *	automatically generated by the tools/uniParse.tcl script.  Do not
 *	modify this file by hand.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * All rights reserved.
 */

/*
 * A 16-bit Unicode character is split into two parts in order to index
 * into the following tables.  The lower OFFSET_BITS comprise an offset
 * into a page of characters.  The upper bits comprise the page number.
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    set last [expr {[llength $pMap] - 1}]
    for {set i 0} {$i <= $last} {incr i} {
	if {$i == [expr {0x10000 >> $shift}]} {
	    set line [string trimright $line " \t,"]
	    puts $f $line
	    set lastpage [expr {[lindex $line end] >> $shift}]
	    puts stdout "lastpage: $lastpage"
	    puts $f "#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6"
	    set line "    ,"
	}
	append line [lindex $pMap $i]
	if {$i != $last} {
	    append line ", "
	}
	if {[string length $line] > 70} {







|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    set last [expr {[llength $pMap] - 1}]
    for {set i 0} {$i <= $last} {incr i} {
	if {$i == [expr {0x10000 >> $shift}]} {
	    set line [string trimright $line " \t,"]
	    puts $f $line
	    set lastpage [expr {[lindex $line end] >> $shift}]
	    puts stdout "lastpage: $lastpage"
	    puts $f "#if TCL_UTF_MAX > 3"
	    set line "    ,"
	}
	append line [lindex $pMap $i]
	if {$i != $last} {
	    append line ", "
	}
	if {[string length $line] > 70} {
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    set line "    "
    set lasti [expr {[llength $pages] - 1}]
    for {set i 0} {$i <= $lasti} {incr i} {
	set page [lindex $pages $i]
	set lastj [expr {[llength $page] - 1}]
	if {$i == ($lastpage + 1)} {
	    puts $f [string trimright $line " \t,"]
	    puts $f "#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6"
	    set line "    ,"
	}
	for {set j 0} {$j <= $lastj} {incr j} {
	    append line [lindex $page $j]
	    if {$j != $lastj || $i != $lasti} {
		append line ", "
	    }







|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    set line "    "
    set lasti [expr {[llength $pages] - 1}]
    for {set i 0} {$i <= $lasti} {incr i} {
	set page [lindex $pages $i]
	set lastj [expr {[llength $page] - 1}]
	if {$i == ($lastpage + 1)} {
	    puts $f [string trimright $line " \t,"]
	    puts $f "#if TCL_UTF_MAX > 3"
	    set line "    ,"
	}
	for {set j 0} {$j <= $lastj} {incr j} {
	    append line [lindex $page $j]
	    if {$j != $lastj || $i != $lasti} {
		append line ", "
	    }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
	    puts $f [string trimright $line]
	    set line "    "
	}
    }
    puts $f $line
    puts -nonewline $f "};

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= [format 0x%X $next])
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1F0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.
 */








|
|

|







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
	    puts $f [string trimright $line]
	    set line "    "
	}
    }
    puts $f $line
    puts -nonewline $f "};

#if TCL_UTF_MAX > 3
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1fffff) >= [format 0x%x $next])
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1f0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.
 */

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

/*
 * The following macros extract the fields of the character info.  The
 * GetDelta() macro is complicated because we can't rely on the C compiler
 * to do sign extension on right shifts.
 */

#define GetCaseType(info) (((info) & 0xE0) >> 5)
#define GetCategory(ch) (GetUniCharInfo(ch) & 0x1F)
#define GetDelta(info) ((info) >> 8)

/*
 * This macro extracts the information about a character from the
 * Unicode character tables.
 */

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0x1FFFFF) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\])
#else
#   define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0xFFFF) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\])
#endif
"

    close $f
}

uni::main

return







|
|







|
|

|









388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

/*
 * The following macros extract the fields of the character info.  The
 * GetDelta() macro is complicated because we can't rely on the C compiler
 * to do sign extension on right shifts.
 */

#define GetCaseType(info) (((info) & 0xe0) >> 5)
#define GetCategory(ch) (GetUniCharInfo(ch) & 0x1f)
#define GetDelta(info) ((info) >> 8)

/*
 * This macro extracts the information about a character from the
 * Unicode character tables.
 */

#if TCL_UTF_MAX > 3
#   define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0x1fffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\])
#else
#   define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0xffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\])
#endif
"

    close $f
}

uni::main

return

Changes to unix/Makefile.in.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

prefix			= @prefix@
exec_prefix		= @exec_prefix@
bindir			= @bindir@
libdir			= @libdir@
includedir		= @includedir@
datarootdir		= @datarootdir@
runstatedir		= @runstatedir@
mandir			= @mandir@

# The following definition can be set to non-null for special systems like AFS
# with replication. It allows the pathnames used for installation to be
# different than those used for actually reference files at run-time.
# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT		= $(DESTDIR)







<







24
25
26
27
28
29
30

31
32
33
34
35
36
37

prefix			= @prefix@
exec_prefix		= @exec_prefix@
bindir			= @bindir@
libdir			= @libdir@
includedir		= @includedir@
datarootdir		= @datarootdir@

mandir			= @mandir@

# The following definition can be set to non-null for special systems like AFS
# with replication. It allows the pathnames used for installation to be
# different than those used for actually reference files at run-time.
# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT		= $(DESTDIR)
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
SHELL			= @MAKEFILE_SHELL@

# Tcl used to let the configure script choose which program to use for
# installing, but there are just too many different versions of "install"
# around; better to use the install-sh script that comes with the
# distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM	= -s
INSTALL_STRIP_LIBRARY	= -S -x

INSTALL			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755








|
|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
SHELL			= @MAKEFILE_SHELL@

# Tcl used to let the configure script choose which program to use for
# installing, but there are just too many different versions of "install"
# around; better to use the install-sh script that comes with the
# distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM   = -s
INSTALL_STRIP_LIBRARY   = -S -x

INSTALL			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755

169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
# the symbols are normally set by the configure script. You shouldn't normally
# need to modify any of these definitions by hand.

STLIB_LD		= @STLIB_LD@
SHLIB_LD		= @SHLIB_LD@
SHLIB_CFLAGS		= @SHLIB_CFLAGS@
SHLIB_LD_LIBS		= @SHLIB_LD_LIBS@
SHLIB_LD_FLAGS		= @SHLIB_LD_FLAGS@
TCL_SHLIB_LD_EXTRAS	= @TCL_SHLIB_LD_EXTRAS@

SHLIB_SUFFIX		= @SHLIB_SUFFIX@


DLTEST_TARGETS		= dltest.marker

# Additional search flags needed to find the various shared libraries at
# run-time. The first symbol is for use when creating a binary with cc, and
# the second is for use when running ld directly.
CC_SEARCH_FLAGS	= @CC_SEARCH_FLAGS@







<



>







168
169
170
171
172
173
174

175
176
177
178
179
180
181
182
183
184
185
# the symbols are normally set by the configure script. You shouldn't normally
# need to modify any of these definitions by hand.

STLIB_LD		= @STLIB_LD@
SHLIB_LD		= @SHLIB_LD@
SHLIB_CFLAGS		= @SHLIB_CFLAGS@
SHLIB_LD_LIBS		= @SHLIB_LD_LIBS@

TCL_SHLIB_LD_EXTRAS	= @TCL_SHLIB_LD_EXTRAS@

SHLIB_SUFFIX		= @SHLIB_SUFFIX@
#SHLIB_SUFFIX		=

DLTEST_TARGETS		= dltest.marker

# Additional search flags needed to find the various shared libraries at
# run-time. The first symbol is for use when creating a binary with cc, and
# the second is for use when running ld directly.
CC_SEARCH_FLAGS	= @CC_SEARCH_FLAGS@
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# Generic lib name used in rules that apply to tcl and tk
LIB_FILE		= ${TCL_LIB_FILE}

TCL_LIB_FLAG		= @TCL_LIB_FLAG@
#TCL_LIB_FLAG		= -ltcl

# support for embedded libraries on Darwin / Mac OS X
DYLIB_INSTALL_DIR	= $(libdir)

#--------------------------------------------------------------------------
# The information below is modified by the configure script when Makefile is
# generated from Makefile.in. You shouldn't normally modify any of this stuff
# by hand.
#--------------------------------------------------------------------------








|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# Generic lib name used in rules that apply to tcl and tk
LIB_FILE		= ${TCL_LIB_FILE}

TCL_LIB_FLAG		= @TCL_LIB_FLAG@
#TCL_LIB_FLAG		= -ltcl

# support for embedded libraries on Darwin / Mac OS X
DYLIB_INSTALL_DIR	= ${LIB_RUNTIME_DIR}

#--------------------------------------------------------------------------
# The information below is modified by the configure script when Makefile is
# generated from Makefile.in. You shouldn't normally modify any of this stuff
# by hand.
#--------------------------------------------------------------------------

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
# won't work in the case where the compilation directory isn't the same as the
# source directory.
#
# Specifying TESTFLAGS on the command line is the standard way to pass args to
# tcltest, ie:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"

test: test-tcl

test-tcl: tcltest@EXEEXT@
	@LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tcltest@EXEEXT@ $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)

gdb-test: tcltest@EXEEXT@
	@echo "set env @LD_LIBRARY_PATH_VAR@=\"`pwd`:$${@LD_LIBRARY_PATH_VAR@}\"" > gdb.run
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run







<
<
|







596
597
598
599
600
601
602


603
604
605
606
607
608
609
610
# won't work in the case where the compilation directory isn't the same as the
# source directory.
#
# Specifying TESTFLAGS on the command line is the standard way to pass args to
# tcltest, ie:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"



test: tcltest@EXEEXT@
	@LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tcltest@EXEEXT@ $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)

gdb-test: tcltest@EXEEXT@
	@echo "set env @LD_LIBRARY_PATH_VAR@=\"`pwd`:$${@LD_LIBRARY_PATH_VAR@}\"" > gdb.run
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
715
716
717
718
719
720
721
722

723
724
725

726
727
728
729
730
731
732
733
734

# Note: before running ranlib below, must cd to target directory because some
# ranlibs write to current directory, and this might not always be possible
# (e.g. if installing as root).

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \
		"$(CONFIG_INSTALL_DIR)" ; do \

	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \

	    fi; \
	done
	@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
	@@INSTALL_LIB@
	@chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
	@echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)@EXEEXT@"
	@$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)@EXEEXT@"
	@echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)/tclConfig.sh"







|
>



>
|
|







712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

# Note: before running ranlib below, must cd to target directory because some
# ranlibs write to current directory, and this might not always be possible
# (e.g. if installing as root).

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \
		"$(CONFIG_INSTALL_DIR)"; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
		else true; \
		fi; \
	    done;
	@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
	@@INSTALL_LIB@
	@chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
	@echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)@EXEEXT@"
	@$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)@EXEEXT@"
	@echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)/tclConfig.sh"
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808

809
810
811

812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840

841
842
843

844
845
846
847
848
849
850
851
852

853
854
855

856
857
858
859
860
861

862
863
864
865

866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/";
	@for i in $(TOP_DIR)/library/http1.0/*.tcl ; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \
	    done;
	@echo "Installing package http 2.7.15 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/http-2.7.15.tm;
	@echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/";
	@for i in $(TOP_DIR)/library/opt/*.tcl ; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
	    done;
	@echo "Installing package msgcat 1.5.2 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.5.2.tm;
	@echo "Installing package tcltest 2.5.3 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/tcltest-2.5.3.tm;

	@echo "Installing package platform 1.0.18 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.18.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform/shell-1.1.4.tm;

	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"
	@for i in $(TOP_DIR)/library/encoding/*.enc; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done
	@if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ] ; then \
	    echo "Customizing tcl module path"; \
	    echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \
	        "$(SCRIPT_INSTALL_DIR)/tm.tcl"; \
	fi

install-tzdata:
	@for i in tzdata; do \

	    if [ ! -d "$(SCRIPT_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/$$i"; \

	    fi; \
	done
	@echo "Installing time zone files to $(SCRIPT_INSTALL_DIR)/tzdata/"
	@for i in $(TOP_DIR)/library/tzdata/*; do \
	    if [ -d $$i ] ; then \
		ii=`basename $$i`; \
		if [ ! -d "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii" ] ; then \
		    $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii"; \
		fi; \
		for j in $$i/*; do \
		    if [ -d $$j ] ; then \
			jj=`basename $$j`; \
			if [ ! -d "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii/$$jj" ] ; then \
			    $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii/$$jj"; \
			fi; \
			for k in $$j/*; do \
			    $(INSTALL_DATA) $$k "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii/$$jj"; \
			done; \
		    else \
			$(INSTALL_DATA) $$j "$(SCRIPT_INSTALL_DIR)/tzdata/$$ii"; \
		    fi; \
		done; \
	    else \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/tzdata"; \
	    fi; \
	done

install-msgs:
	@for i in msgs; do \

	    if [ ! -d "$(SCRIPT_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/$$i"; \

	    fi; \
	done
	@echo "Installing message catalog files to $(SCRIPT_INSTALL_DIR)/msgs/"
	@for i in $(TOP_DIR)/library/msgs/*.msg; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/msgs"; \
	done

install-doc: doc
	@for i in "$(MAN_INSTALL_DIR)" "$(MAN1_INSTALL_DIR)" "$(MAN3_INSTALL_DIR)" "$(MANN_INSTALL_DIR)"; do \

	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \

	    fi; \
	done
	@echo "Installing and cross-linking top-level (.1) docs to $(MAN1_INSTALL_DIR)/"
	@for i in $(TOP_DIR)/doc/*.1; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN1_INSTALL_DIR)"; \
	done

	@echo "Installing and cross-linking C API (.3) docs to $(MAN3_INSTALL_DIR)/"
	@for i in $(TOP_DIR)/doc/*.3; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN3_INSTALL_DIR)"; \
	done

	@echo "Installing and cross-linking command (.n) docs to $(MANN_INSTALL_DIR)/";
	@for i in $(TOP_DIR)/doc/*.n; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MANN_INSTALL_DIR)"; \
	done

# Optional target to install private headers
install-private-headers: libraries
	@for i in "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
		else true; \
	    fi; \
	done
	@echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/";
	@for i in $(GENERIC_DIR)/tclInt.h $(GENERIC_DIR)/tclIntDecls.h \
		$(GENERIC_DIR)/tclIntPlatDecls.h $(GENERIC_DIR)/tclPort.h \
		$(UNIX_DIR)/tclUnixPort.h; \
	    do \
	    $(INSTALL_DATA) $$i "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	done
	@if test -f tclConfig.h; then\
	    $(INSTALL_DATA) tclConfig.h "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	fi

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
#	$(SHELL) config.status

clean:
	rm -rf *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
		errors ${TCL_EXE} tcltest@EXEEXT@ lib.exp Tcl @DTRACE_HDR@ \
		*.zip *.vfs
	cd dltest ; $(MAKE) clean

distclean: clean
	rm -rf Makefile config.status config.cache config.log tclConfig.sh \
		$(PACKAGE).* prototype tclConfig.h *.plist Tcl.framework \
		tcl.pc
	cd dltest ; $(MAKE) distclean







|
|







|
|

|
|



|
|
|
|
|


|



|
>
|

|
>
|
|

|


|
|

|


|
|

|
|


|



|

|


|
>
|

|
>
|
|

|
|
|


|
>



>
|
|
|



>
|



>













|
|






|


|







|
|
<







772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/";
	@for i in $(TOP_DIR)/library/http1.0/*.tcl ; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \
	    done;
	@echo "Installing package http 2.7.14 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/http-2.7.14.tm;
	@echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/";
	@for i in $(TOP_DIR)/library/opt/*.tcl ; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
	    done;
	@echo "Installing package msgcat 1.5.2 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.5.2.tm;
	@echo "Installing package tcltest 2.3.8 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/tcltest-2.3.8.tm;

	@echo "Installing package platform 1.0.14 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.14.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform/shell-1.1.4.tm;

	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/";
	@for i in $(TOP_DIR)/library/encoding/*.enc ; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/encoding; \
	done;
	@if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ]; then \
	    echo "Customizing tcl module path"; \
	    echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \
	        "$(SCRIPT_INSTALL_DIR)"/tm.tcl; \
	fi

install-tzdata:
	@for i in tzdata; \
	    do \
	    if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/$$i; \
		else true; \
		fi; \
	    done;
	@echo "Installing time zone files to $(SCRIPT_INSTALL_DIR)/tzdata/"
	@for i in $(TOP_DIR)/library/tzdata/* ; do \
	    if [ -d $$i ] ; then \
		ii=`basename $$i`; \
		if [ ! -d "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii ] ; then \
		    $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii; \
		fi; \
		for j in $$i/* ; do \
		    if [ -d $$j ] ; then \
			jj=`basename $$j`; \
			if [ ! -d "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj ] ; then \
			    $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj; \
			fi; \
			for k in $$j/* ; do \
			    $(INSTALL_DATA) $$k "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj; \
			done; \
		    else \
			$(INSTALL_DATA) $$j "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii; \
		    fi; \
		done; \
	    else \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/tzdata; \
	    fi; \
	done;

install-msgs:
	@for i in msgs; \
	    do \
	    if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/$$i; \
		else true; \
		fi; \
	    done;
	@echo "Installing message catalog files to $(SCRIPT_INSTALL_DIR)/msgs/"
	@for i in $(TOP_DIR)/library/msgs/*.msg ; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/msgs; \
	done;

install-doc: doc
	@for i in "$(MAN_INSTALL_DIR)" "$(MAN1_INSTALL_DIR)" "$(MAN3_INSTALL_DIR)" "$(MANN_INSTALL_DIR)" ; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
		else true; \
		fi; \
	    done;
	@echo "Installing and cross-linking top-level (.1) docs to $(MAN1_INSTALL_DIR)/";
	@for i in $(TOP_DIR)/doc/*.1; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN1_INSTALL_DIR)"; \
	done

	@echo "Installing and cross-linking C API (.3) docs to $(MAN3_INSTALL_DIR)/";
	@for i in $(TOP_DIR)/doc/*.3; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN3_INSTALL_DIR)"; \
	done

	@echo "Installing and cross-linking command (.n) docs to $(MANN_INSTALL_DIR)/";
	@for i in $(TOP_DIR)/doc/*.n; do \
	    $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MANN_INSTALL_DIR)"; \
	done

# Optional target to install private headers
install-private-headers: libraries
	@for i in "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
		else true; \
		fi; \
	    done;
	@echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/";
	@for i in $(GENERIC_DIR)/tclInt.h $(GENERIC_DIR)/tclIntDecls.h \
		$(GENERIC_DIR)/tclIntPlatDecls.h $(GENERIC_DIR)/tclPort.h \
		$(UNIX_DIR)/tclUnixPort.h; \
	    do \
	    $(INSTALL_DATA) $$i "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    done;
	@if test -f tclConfig.h; then\
	    $(INSTALL_DATA) tclConfig.h "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    fi;

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
#	$(SHELL) config.status

clean:
	rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
		errors ${TCL_EXE} tcltest@EXEEXT@ lib.exp Tcl @DTRACE_HDR@

	cd dltest ; $(MAKE) clean

distclean: clean
	rm -rf Makefile config.status config.cache config.log tclConfig.sh \
		$(PACKAGE).* prototype tclConfig.h *.plist Tcl.framework \
		tcl.pc
	cd dltest ; $(MAKE) distclean
1642
1643
1644
1645
1646
1647
1648



1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
# distribution. DISTDIR must be an absolute path name.
#

DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME	 = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR	 = $(DISTROOT)/$(DISTNAME)



$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
	cd $(MAC_OSX_DIR); autoconf

$(TOP_DIR)/manifest.uuid:
	printf "git." >$(TOP_DIR)/manifest.uuid
	git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid

dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in $(MAC_OSX_DIR)/configure $(TOP_DIR)/manifest.uuid genstubs
	rm -rf $(DISTDIR)
	mkdir -p $(DISTDIR)/unix
	cp -p $(TOP_DIR)/manifest.uuid $(DISTDIR)
	cp -p $(UNIX_DIR)/*.[ch] $(DISTDIR)/unix
	cp $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
	chmod 664 $(DISTDIR)/unix/Makefile.in
	cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.in \
		$(UNIX_DIR)/tcl.m4 $(UNIX_DIR)/aclocal.m4 \
		$(UNIX_DIR)/tclConfig.sh.in $(UNIX_DIR)/install-sh \
		$(UNIX_DIR)/README $(UNIX_DIR)/ldAix $(UNIX_DIR)/tcl.spec \
		$(UNIX_DIR)/installManPage $(UNIX_DIR)/tclConfig.h.in \
		$(UNIX_DIR)/tcl.pc.in $(DISTDIR)/unix
	chmod 775 $(DISTDIR)/unix/configure
	chmod 775 $(DISTDIR)/unix/ldAix
	@mkdir $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.[cdh] $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/tclGetDate.y $(DISTDIR)/generic
	cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog $(TOP_DIR)/README.md \
		$(TOP_DIR)/ChangeLog.[12]??? $(TOP_DIR)/license.terms \
		$(DISTDIR)
	@mkdir $(DISTDIR)/library
	cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
		$(TOP_DIR)/library/tclIndex $(DISTDIR)/library
	for i in http1.0 http opt msgcat reg dde tcltest platform; \
	    do \







>
>
>


|
|
<
<

|


<









|






|







1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661


1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
# distribution. DISTDIR must be an absolute path name.
#

DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME	 = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR	 = $(DISTROOT)/$(DISTNAME)
$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.in $(UNIX_DIR)/tcl.m4 \
		$(UNIX_DIR)/aclocal.m4
	cd $(UNIX_DIR); autoconf
$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
	cd $(MAC_OSX_DIR); autoconf
$(UNIX_DIR)/tclConfig.h.in: $(MAC_OSX_DIR)/configure
	cd $(MAC_OSX_DIR); autoheader; touch $@



dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in $(MAC_OSX_DIR)/configure genstubs
	rm -rf $(DISTDIR)
	mkdir -p $(DISTDIR)/unix

	cp -p $(UNIX_DIR)/*.[ch] $(DISTDIR)/unix
	cp $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
	chmod 664 $(DISTDIR)/unix/Makefile.in
	cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.in \
		$(UNIX_DIR)/tcl.m4 $(UNIX_DIR)/aclocal.m4 \
		$(UNIX_DIR)/tclConfig.sh.in $(UNIX_DIR)/install-sh \
		$(UNIX_DIR)/README $(UNIX_DIR)/ldAix $(UNIX_DIR)/tcl.spec \
		$(UNIX_DIR)/installManPage $(UNIX_DIR)/tclConfig.h.in \
		$(UNIX_DIR)/tcl.pc.in $(DISTDIR)/unix
	chmod 775 $(DISTDIR)/unix/configure $(DISTDIR)/unix/configure.in
	chmod 775 $(DISTDIR)/unix/ldAix
	@mkdir $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.[cdh] $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic
	cp -p $(GENERIC_DIR)/tclGetDate.y $(DISTDIR)/generic
	cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog $(TOP_DIR)/README \
		$(TOP_DIR)/ChangeLog.[12]??? $(TOP_DIR)/license.terms \
		$(DISTDIR)
	@mkdir $(DISTDIR)/library
	cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
		$(TOP_DIR)/library/tclIndex $(DISTDIR)/library
	for i in http1.0 http opt msgcat reg dde tcltest platform; \
	    do \
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
		 $(DISTDIR)/$(PACKAGE)/$(VERSION)/`arch`=`arch` \
	| $(TCL_EXE) $(UNIX_DIR)/mkProto.tcl \
		$(VERSION) $(UNIX_DIR) > prototype
	pkgmk -o -d . -f prototype -a `arch`
	pkgtrans -s . $(PACKAGE).`arch` $(PACKAGE)
	rm -rf $(PACKAGE)

#--------------------------------------------------------------------------
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#--------------------------------------------------------------------------

.PHONY: all binaries libraries objs doc html html-tcl html-tk test runtest
.PHONY: install install-strip install-binaries install-libraries
.PHONY: install-headers install-private-headers install-doc
.PHONY: clean distclean depend genstubs checkstubs checkexports checkuchar
.PHONY: shell gdb valgrind valgrindshell dist alldist rpm
.PHONY: tclLibObjs tcltest-real test-tcl gdb-test ro-test trace-test xttest
.PHONY: topDirName gendate gentommath_h trace-shell checkdoc
.PHONY: install-tzdata install-msgs
.PHONY: packages configure-packages test-packages clean-packages
.PHONY: dist-packages distclean-packages install-packages
.PHONY: install-libraries-zipfs-shared install-libraries-zipfs-static tclzipfile

#--------------------------------------------------------------------------
# DO NOT DELETE THIS LINE -- make depend depends on it.








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

1856
1857
1858
1859
1860
1861
1862
1863

















1864
		 $(DISTDIR)/$(PACKAGE)/$(VERSION)/`arch`=`arch` \
	| $(TCL_EXE) $(UNIX_DIR)/mkProto.tcl \
		$(VERSION) $(UNIX_DIR) > prototype
	pkgmk -o -d . -f prototype -a `arch`
	pkgtrans -s . $(PACKAGE).`arch` $(PACKAGE)
	rm -rf $(PACKAGE)

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

















# DO NOT DELETE THIS LINE -- make depend depends on it.

Changes to unix/README.

161
162
163
164
165
166
167
168
169
should then see a printout of the test files processed. If any errors occur,
you'll see a much more substantial printout for each error. See the README
file in the "tests" directory for more information on the test suite. Note:
don't run the tests as superuser: this will cause several of them to fail. If
a test is failing consistently, please send us a bug report with as much
detail as you can manage to our tracker:

	https://core.tcl-lang.org/tcl/reportlist








|

161
162
163
164
165
166
167
168
169
should then see a printout of the test files processed. If any errors occur,
you'll see a much more substantial printout for each error. See the README
file in the "tests" directory for more information on the test suite. Note:
don't run the tests as superuser: this will cause several of them to fail. If
a test is failing consistently, please send us a bug report with as much
detail as you can manage to our tracker:

	http://core.tcl.tk/tcl/reportlist

Changes to unix/configure.

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
#define inline $ac_val
#endif
_ACEOF
    ;;
esac



#--------------------------------------------------------------------
# Supply substitutes for missing POSIX header files.  Special notes:
#	- stdlib.h doesn't define strtol, strtoul, or
#	  strtod insome versions of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure







<







2426
2427
2428
2429
2430
2431
2432

2433
2434
2435
2436
2437
2438
2439
#define inline $ac_val
#endif
_ACEOF
    ;;
esac



#--------------------------------------------------------------------
# Supply substitutes for missing POSIX header files.  Special notes:
#	- stdlib.h doesn't define strtol, strtoul, or
#	  strtod insome versions of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ctype.h>
#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \







<







2794
2795
2796
2797
2798
2799
2800

2801
2802
2803
2804
2805
2806
2807
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ctype.h>

#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
6275
6276
6277
6278
6279
6280
6281








6282
6283
6284
6285
6286
6287
6288
    # Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;








    if test "$tcl_ok" = "yes" ; then
	echo "$as_me:$LINENO: result: shared" >&5
echo "${ECHO_T}shared" >&6
	SHARED_BUILD=1
    else
	echo "$as_me:$LINENO: result: static" >&5
echo "${ECHO_T}static" >&6







>
>
>
>
>
>
>
>







6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
    # Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	echo "$as_me:$LINENO: result: shared" >&5
echo "${ECHO_T}shared" >&6
	SHARED_BUILD=1
    else
	echo "$as_me:$LINENO: result: static" >&5
echo "${ECHO_T}static" >&6
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi

fi
echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
echo "${ECHO_T}$tcl_cv_sys_version" >&6
    system=$tcl_cv_sys_version







<
<
<







6533
6534
6535
6536
6537
6538
6539



6540
6541
6542
6543
6544
6545
6546

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi



	    fi
	fi

fi
echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
echo "${ECHO_T}$tcl_cv_sys_version" >&6
    system=$tcl_cv_sys_version
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    CFLAGS_OPTIMIZE=-O
    if test "$GCC" = yes; then

	CFLAGS_WARNING="-Wall -Wpointer-arith"

else
  CFLAGS_WARNING=""
fi

    if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.







|







6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    CFLAGS_OPTIMIZE=-O
    if test "$GCC" = yes; then

	CFLAGS_WARNING="-Wall"

else
  CFLAGS_WARNING=""
fi

    if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*|MINGW32_*|MSYS_*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o tclWinError.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""







|







6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*|MINGW32*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o tclWinError.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-lroot"
	    echo "$as_me:$LINENO: checking for inet_ntoa in -lnetwork" >&5
echo $ECHO_N "checking for inet_ntoa in -lnetwork... $ECHO_C" >&6
if test "${ac_cv_lib_network_inet_ntoa+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else







|







7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-lroot"
	    echo "$as_me:$LINENO: checking for inet_ntoa in -lnetwork" >&5
echo $ECHO_N "checking for inet_ntoa in -lnetwork... $ECHO_C" >&6
if test "${ac_cv_lib_network_inet_ntoa+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi







|







7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi
7566
7567
7568
7569
7570
7571
7572

7573
7574
7575
7576
7577
7578
7579
	    arch=`arch -s`
	    case "$arch" in
	    vax)
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""

		;;
	    *)
		case "$arch" in
		alpha|sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)







>







7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
	    arch=`arch -s`
	    case "$arch" in
	    vax)
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)
		case "$arch" in
		alpha|sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
		;;
	    esac
	    case "$arch" in
	    vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    sh)







|







7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
		if test $doRpath = yes; then

		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		LDFLAGS="-Wl,-export-dynamic"
		;;
	    esac
	    case "$arch" in
	    vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    sh)
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652

7653
7654
7655
7656
7657
7658
7659
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    if test "${TCL_THREADS}" = "1"; then

		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"

fi

	    ;;
	DragonFly-*|FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""

	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

	    if test "${TCL_THREADS}" = "1"; then







|




















|







>







7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    if test "${TCL_THREADS}" = "1"; then

		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"

fi

	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    if test $doRpath = yes; then

		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
fi

	    if test "${TCL_THREADS}" = "1"; then
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    if test "$GCC" = yes; then

		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"

else

		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"

fi

	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"







|
|



|
|







8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    if test "$GCC" = yes; then

	    	SHLIB_CFLAGS="-fPIC -melf"
	    	LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"

else

	    	SHLIB_CFLAGS="-Kpic -belf"
	    	LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"

fi

	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
	    if test "$GCC" = yes; then
  use_sunmath=no
else

		arch=`isainfo`
		echo "$as_me:$LINENO: checking whether to use -lsunmath for fp rounding control" >&5
echo $ECHO_N "checking whether to use -lsunmath for fp rounding control... $ECHO_C" >&6
		if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then

			echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
			MATH_LIBS="-lsunmath $MATH_LIBS"
			if test "${ac_cv_header_sunmath_h+set}" = set; then
  echo "$as_me:$LINENO: checking for sunmath.h" >&5
echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6







|







8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
	    if test "$GCC" = yes; then
  use_sunmath=no
else

		arch=`isainfo`
		echo "$as_me:$LINENO: checking whether to use -lsunmath for fp rounding control" >&5
echo $ECHO_N "checking whether to use -lsunmath for fp rounding control... $ECHO_C" >&6
		if test "$arch" = "amd64 i386"; then

			echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
			MATH_LIBS="-lsunmath $MATH_LIBS"
			if test "${ac_cv_header_sunmath_h+set}" = set; then
  echo "$as_me:$LINENO: checking for sunmath.h" >&5
echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
		if test "$use_sunmath" = yes; then
  textmode=textoff
else
  textmode=text
fi

		case $system in
		    SunOS-5.[1-9][0-9]*|SunOS-5.[7-9])
			SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
		    *)
			SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'








|







8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
		if test "$use_sunmath" = yes; then
  textmode=textoff
else
  textmode=text
fi

		case $system in
		    SunOS-5.[1-9][0-9]*)
			SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
		    *)
			SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'

8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
    # standard manufacturer compiler.

    if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    IRIX*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac
fi









|

|







8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
    # standard manufacturer compiler.

    if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*) ;;
	    IRIX*) ;;
	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac
fi


12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193

cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYADDR 1
_ACEOF


    else

    # Avoids picking hidden internal symbol from libc
    echo "$as_me:$LINENO: checking whether gethostbyname_r is declared" >&5
echo $ECHO_N "checking whether gethostbyname_r is declared... $ECHO_C" >&6
if test "${ac_cv_have_decl_gethostbyname_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <netdb.h>

int
main ()
{
#ifndef gethostbyname_r
  char *p = (char *) gethostbyname_r;
#endif

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_have_decl_gethostbyname_r=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_have_decl_gethostbyname_r=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_have_decl_gethostbyname_r" >&5
echo "${ECHO_T}$ac_cv_have_decl_gethostbyname_r" >&6
if test $ac_cv_have_decl_gethostbyname_r = yes; then

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYNAME_R 1
_ACEOF


    tcl_cv_api_gethostbyname_r=yes
else
  cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYNAME_R 0
_ACEOF

tcl_cv_api_gethostbyname_r=no
fi




    if test "$tcl_cv_api_gethostbyname_r" = yes; then
	echo "$as_me:$LINENO: checking for gethostbyname_r" >&5
echo $ECHO_N "checking for gethostbyname_r... $ECHO_C" >&6
if test "${ac_cv_func_gethostbyname_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







12106
12107
12108
12109
12110
12111
12112















































































12113
12114
12115
12116
12117
12118
12119

cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYADDR 1
_ACEOF


    else















































































	echo "$as_me:$LINENO: checking for gethostbyname_r" >&5
echo $ECHO_N "checking for gethostbyname_r... $ECHO_C" >&6
if test "${ac_cv_func_gethostbyname_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
#define HAVE_GETHOSTBYNAME_R 1
_ACEOF

    fi

fi

    fi


    # Avoids picking hidden internal symbol from libc
    echo "$as_me:$LINENO: checking whether gethostbyaddr_r is declared" >&5
echo $ECHO_N "checking whether gethostbyaddr_r is declared... $ECHO_C" >&6
if test "${ac_cv_have_decl_gethostbyaddr_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <netdb.h>

int
main ()
{
#ifndef gethostbyaddr_r
  char *p = (char *) gethostbyaddr_r;
#endif

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_have_decl_gethostbyaddr_r=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_have_decl_gethostbyaddr_r=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_have_decl_gethostbyaddr_r" >&5
echo "${ECHO_T}$ac_cv_have_decl_gethostbyaddr_r" >&6
if test $ac_cv_have_decl_gethostbyaddr_r = yes; then

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYADDR_R 1
_ACEOF


    tcl_cv_api_gethostbyaddr_r=yes
else
  cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYADDR_R 0
_ACEOF

tcl_cv_api_gethostbyaddr_r=no
fi




    if test "$tcl_cv_api_gethostbyaddr_r" = yes; then
	echo "$as_me:$LINENO: checking for gethostbyaddr_r" >&5
echo $ECHO_N "checking for gethostbyaddr_r... $ECHO_C" >&6
if test "${ac_cv_func_gethostbyaddr_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







12424
12425
12426
12427
12428
12429
12430

















































































12431
12432
12433
12434
12435
12436
12437
#define HAVE_GETHOSTBYNAME_R 1
_ACEOF

    fi

fi


















































































	echo "$as_me:$LINENO: checking for gethostbyaddr_r" >&5
echo $ECHO_N "checking for gethostbyaddr_r... $ECHO_C" >&6
if test "${ac_cv_func_gethostbyaddr_r+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
#define HAVE_GETHOSTBYADDR_R 1
_ACEOF

    fi

fi

    fi

    fi
fi

#---------------------------------------------------------------------------
#	Determine which interface to use to talk to the serial port.
#	Note that #include lines must begin in leftmost column for
#	some compilers to recognize them as preprocessor directives.







<
<







12677
12678
12679
12680
12681
12682
12683


12684
12685
12686
12687
12688
12689
12690
#define HAVE_GETHOSTBYADDR_R 1
_ACEOF

    fi

fi



    fi
fi

#---------------------------------------------------------------------------
#	Determine which interface to use to talk to the serial port.
#	Note that #include lines must begin in leftmost column for
#	some compilers to recognize them as preprocessor directives.
14002
14003
14004
14005
14006
14007
14008
14009
14010
14011
14012
14013
14014
14015
14016
#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
    echo "$as_me:$LINENO: checking for struct stat.st_blocks" >&5
echo $ECHO_N "checking for struct stat.st_blocks... $ECHO_C" >&6
if test "${ac_cv_member_struct_stat_st_blocks+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF







|







13845
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
echo "$as_me:$LINENO: checking for struct stat.st_blocks" >&5
echo $ECHO_N "checking for struct stat.st_blocks... $ECHO_C" >&6
if test "${ac_cv_member_struct_stat_st_blocks+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
14389
14390
14391
14392
14393
14394
14395
14396
14397
14398
14399
14400
14401
14402
14403
14404
#define NO_FSTATFS 1
_ACEOF

fi


#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit data, this
#       checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for working memcmp" >&5
echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6
if test "${ac_cv_func_memcmp_working+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else







|
|







14232
14233
14234
14235
14236
14237
14238
14239
14240
14241
14242
14243
14244
14245
14246
14247
#define NO_FSTATFS 1
_ACEOF

fi


#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit
#       data, this checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for working memcmp" >&5
echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6
if test "${ac_cv_func_memcmp_working+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
14476
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492
  *" memcmp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;;
esac



#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems have no memmove
#       (we assume they have bcopy instead). {The replacement define is in
#       compat/string.h}
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for memmove" >&5
echo $ECHO_N "checking for memmove... $ECHO_C" >&6
if test "${ac_cv_func_memmove+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else







|
|
|







14319
14320
14321
14322
14323
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335
  *" memcmp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;;
esac



#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems
#       have no memmove (we assume they have bcopy instead).
#       {The replacement define is in compat/string.h}
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for memmove" >&5
echo $ECHO_N "checking for memmove... $ECHO_C" >&6
if test "${ac_cv_func_memmove+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598
14599
14600
14601
14602
14603
14604
#define NO_STRING_H 1
_ACEOF

fi


#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even even if
#	the original string is empty.
#--------------------------------------------------------------------


    echo "$as_me:$LINENO: checking for strstr" >&5
echo $ECHO_N "checking for strstr... $ECHO_C" >&6
if test "${ac_cv_func_strstr+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6







|
|







14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
#define NO_STRING_H 1
_ACEOF

fi


#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even
#	even if the original string is empty.
#--------------------------------------------------------------------


    echo "$as_me:$LINENO: checking for strstr" >&5
echo $ECHO_N "checking for strstr... $ECHO_C" >&6
if test "${ac_cv_func_strstr+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
14705
14706
14707
14708
14709
14710
14711
14712
14713
14714
14715
14716
14717
14718
14719
14720
14721
14722
14723
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <stdlib.h>
#include <string.h>
int main() {
    extern char *strstr(const char *, const char *);
    exit(strstr("\0test", "test") ? 1 : 0);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?







<
<
<

|







14548
14549
14550
14551
14552
14553
14554



14555
14556
14557
14558
14559
14560
14561
14562
14563
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */



int main() {
    extern int strstr();
    exit(strstr("\0test", "test") ? 1 : 0);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <stdlib.h>
#include <string.h>
int main() {
    extern unsigned long strtoul(const char *, char **, int);
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5







<
<
<

|







14715
14716
14717
14718
14719
14720
14721



14722
14723
14724
14725
14726
14727
14728
14729
14730
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */



int main() {
    extern int strtoul();
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <stdlib.h>
#include <string.h>
int main() {
    extern double strtod(const char *, char **);
    char *term, *string = " +69";
    exit(strtod(string,&term) != 69 || term != string+4);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5







<
<
<

|







14882
14883
14884
14885
14886
14887
14888



14889
14890
14891
14892
14893
14894
14895
14896
14897
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */



int main() {
    extern double strtod();
    char *term, *string = " +69";
    exit(strtod(string,&term) != 69 || term != string+4);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
15219
15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
15232
15233
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		#include <stdlib.h>
		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {







<







15053
15054
15055
15056
15057
15058
15059

15060
15061
15062
15063
15064
15065
15066
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */


		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
15604
15605
15606
15607
15608
15609
15610
15611
15612
15613
15614
15615
15616
15617
15618
15619
15620
15621
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <stdint.h>


int
main ()
{
if ((intptr_t *) 0)
  return 0;
if (sizeof (intptr_t))
  return 0;







<
|
<
<







15437
15438
15439
15440
15441
15442
15443

15444


15445
15446
15447
15448
15449
15450
15451
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

$ac_includes_default


int
main ()
{
if ((intptr_t *) 0)
  return 0;
if (sizeof (intptr_t))
  return 0;
15654
15655
15656
15657
15658
15659
15660

15661
15662
15663
15664

15665





















































15666
















15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5
echo "${ECHO_T}$ac_cv_type_intptr_t" >&6
if test $ac_cv_type_intptr_t = yes; then


cat >>confdefs.h <<_ACEOF
#define HAVE_INTPTR_T 1
_ACEOF
























































fi
















echo "$as_me:$LINENO: checking for uintptr_t" >&5
echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6
if test "${ac_cv_type_uintptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <stdint.h>


int
main ()
{
if ((uintptr_t *) 0)
  return 0;
if (sizeof (uintptr_t))
  return 0;







>
|



>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











<
|
<
<







15484
15485
15486
15487
15488
15489
15490
15491
15492
15493
15494
15495
15496
15497
15498
15499
15500
15501
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514
15515
15516
15517
15518
15519
15520
15521
15522
15523
15524
15525
15526
15527
15528
15529
15530
15531
15532
15533
15534
15535
15536
15537
15538
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562
15563
15564
15565
15566
15567
15568
15569
15570
15571
15572
15573
15574
15575
15576
15577
15578

15579


15580
15581
15582
15583
15584
15585
15586
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5
echo "${ECHO_T}$ac_cv_type_intptr_t" >&6
if test $ac_cv_type_intptr_t = yes; then


cat >>confdefs.h <<\_ACEOF
#define HAVE_INTPTR_T 1
_ACEOF

else

    echo "$as_me:$LINENO: checking for pointer-size signed integer type" >&5
echo $ECHO_N "checking for pointer-size signed integer type... $ECHO_C" >&6
if test "${tcl_cv_intptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_ok=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_ok=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
echo "$as_me:$LINENO: result: $tcl_cv_intptr_t" >&5
echo "${ECHO_T}$tcl_cv_intptr_t" >&6
    if test "$tcl_cv_intptr_t" != none; then

cat >>confdefs.h <<_ACEOF
#define intptr_t $tcl_cv_intptr_t
_ACEOF

    fi

fi

echo "$as_me:$LINENO: checking for uintptr_t" >&5
echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6
if test "${ac_cv_type_uintptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

$ac_includes_default


int
main ()
{
if ((uintptr_t *) 0)
  return 0;
if (sizeof (uintptr_t))
  return 0;
15721
15722
15723
15724
15725
15726
15727

15728
15729
15730
15731






































































15732
15733
15734
15735
15736
15737
15738
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6
if test $ac_cv_type_uintptr_t = yes; then


cat >>confdefs.h <<_ACEOF
#define HAVE_UINTPTR_T 1
_ACEOF








































































fi


#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which







>
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







15619
15620
15621
15622
15623
15624
15625
15626
15627
15628
15629
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659
15660
15661
15662
15663
15664
15665
15666
15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15707
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6
if test $ac_cv_type_uintptr_t = yes; then


cat >>confdefs.h <<\_ACEOF
#define HAVE_UINTPTR_T 1
_ACEOF

else

    echo "$as_me:$LINENO: checking for pointer-size unsigned integer type" >&5
echo $ECHO_N "checking for pointer-size unsigned integer type... $ECHO_C" >&6
if test "${tcl_cv_uintptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_ok=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_ok=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
echo "$as_me:$LINENO: result: $tcl_cv_uintptr_t" >&5
echo "${ECHO_T}$tcl_cv_uintptr_t" >&6
    if test "$tcl_cv_uintptr_t" != none; then

cat >>confdefs.h <<_ACEOF
#define uintptr_t $tcl_cv_uintptr_t
_ACEOF

    fi

fi


#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which
16471
16472
16473
16474
16475
16476
16477
16478
16479
16480
16481
16482
16483
16484
16485
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

	#include <stdlib.h>
	#include <string.h>
	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
	    char *foo, *bar;
	    foo = (char *)strdup(OURVAR);
	    putenv(foo);
	    strcpy((char *)(strchr(foo, '=') + 1), "no");







<







16440
16441
16442
16443
16444
16445
16446

16447
16448
16449
16450
16451
16452
16453
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

	#include <stdlib.h>

	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
	    char *foo, *bar;
	    foo = (char *)strdup(OURVAR);
	    putenv(foo);
	    strcpy((char *)(strchr(foo, '=') + 1), "no");
17868
17869
17870
17871
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881
17882
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
#	Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for fts" >&5
echo $ECHO_N "checking for fts... $ECHO_C" >&6
if test "${tcl_cv_api_fts+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else







|







17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
# Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for fts" >&5
echo $ECHO_N "checking for fts... $ECHO_C" >&6
if test "${tcl_cv_api_fts+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
17943
17944
17945
17946
17947
17948
17949
17950
17951
17952

17953
17954
17955
17956
17957
17958
17959
cat >>confdefs.h <<\_ACEOF
#define HAVE_FTS 1
_ACEOF

fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style non-blocking
#	I/O (O_NONBLOCK) doesn't work or is unimplemented. On these systems
#	(mostly older ones), use the old BSD-style FIONBIO approach instead.

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



for ac_header in sys/ioctl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`







|
|
|
>







17911
17912
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
17923
17924
17925
17926
17927
17928
cat >>confdefs.h <<\_ACEOF
#define HAVE_FTS 1
_ACEOF

fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
#--------------------------------------------------------------------



for ac_header in sys/ioctl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
18274
18275
18276
18277
18278
18279
18280
18281
18282
18283
18284
18285
18286
18287
18288
18289
18290

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi

fi
echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
echo "${ECHO_T}$tcl_cv_sys_version" >&6
    system=$tcl_cv_sys_version







<
<
<







18243
18244
18245
18246
18247
18248
18249



18250
18251
18252
18253
18254
18255
18256

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi



	    fi
	fi

fi
echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
echo "${ECHO_T}$tcl_cv_sys_version" >&6
    system=$tcl_cv_sys_version
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351
18352
18353
18354
18355
18356
fi
echo "$as_me:$LINENO: result: $tcl_ok" >&5
echo "${ECHO_T}$tcl_ok" >&6

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overridden on the configure command line either way.
#------------------------------------------------------------------------

echo "$as_me:$LINENO: checking for timezone data" >&5
echo $ECHO_N "checking for timezone data... $ECHO_C" >&6

# Check whether --with-tzdata or --without-tzdata was given.
if test "${with_tzdata+set}" = set; then







|







18308
18309
18310
18311
18312
18313
18314
18315
18316
18317
18318
18319
18320
18321
18322
fi
echo "$as_me:$LINENO: result: $tcl_ok" >&5
echo "${ECHO_T}$tcl_ok" >&6

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overriden on the configure command line either way.
#------------------------------------------------------------------------

echo "$as_me:$LINENO: checking for timezone data" >&5
echo $ECHO_N "checking for timezone data... $ECHO_C" >&6

# Check whether --with-tzdata or --without-tzdata was given.
if test "${with_tzdata+set}" = set; then
18796
18797
18798
18799
18800
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

test -z "$TCL_LIBRARY" && TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.







|







18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.
18847
18848
18849
18850
18851
18852
18853
18854
18855
18856
18857
18858
18859
18860
18861
	    fi
	    FRAMEWORK_BUILD=0
	fi
    fi

    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xA000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
                        ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"

    TCL_YEAR="`date +%Y`"
fi







|







18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825
18826
18827
	    fi
	    FRAMEWORK_BUILD=0
	fi
    fi

    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
                        ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"

    TCL_YEAR="`date +%Y`"
fi
18881
18882
18883
18884
18885
18886
18887
18888
18889
18890
18891
18892
18893
18894
18895
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)/TclTOC.html"'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh







|







18847
18848
18849
18850
18851
18852
18853
18854
18855
18856
18857
18858
18859
18860
18861
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh
18919
18920
18921
18922
18923
18924
18925
18926
18927
18928
18929
18930
18931
18932
18933
18934
18935

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------








|

|







18885
18886
18887
18888
18889
18890
18891
18892
18893
18894
18895
18896
18897
18898
18899
18900
18901

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
    TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

20128
20129
20130
20131
20132
20133
20134
20135
20136
  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || { (exit 1); exit 1; }
fi










<
20094
20095
20096
20097
20098
20099
20100
20101

  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || { (exit 1); exit 1; }
fi


Changes to unix/configure.in.

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
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

AC_INIT([tcl],[8.5])
AC_PREREQ([2.59])

dnl This is only used when included from macosx/configure.ac
m4_ifdef([SC_USE_CONFIG_HEADERS], [
    AC_CONFIG_HEADERS([tclConfig.h:../unix/tclConfig.h.in])
    AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H  -imacros tclConfig.h"])
    AH_TOP([
    #ifndef _TCLCONFIG
    #define _TCLCONFIG])
    AH_BOTTOM([
    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_VERSION
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */])
])

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"






|












|
|
<







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
#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

AC_INIT([tcl],[8.5])
AC_PREREQ(2.59)

dnl This is only used when included from macosx/configure.ac
m4_ifdef([SC_USE_CONFIG_HEADERS], [
    AC_CONFIG_HEADERS([tclConfig.h:../unix/tclConfig.h.in])
    AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H  -imacros tclConfig.h"])
    AH_TOP([
    #ifndef _TCLCONFIG
    #define _TCLCONFIG])
    AH_BOTTOM([
    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME

    #endif /* _TCLCONFIG */])
])

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"
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
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE


#--------------------------------------------------------------------
# Supply substitutes for missing POSIX header files.  Special notes:
#	- stdlib.h doesn't define strtol, strtoul, or
#	  strtod insome versions of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure
#--------------------------------------------------------------------

SC_MISSING_POSIX_HEADERS

#------------------------------------------------------------------------
# If we're using GCC, see if the compiler understands -pipe.  If so, use it.
# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    AC_CACHE_CHECK([if the compiler understands -pipe],
	tcl_cv_cc_pipe, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no])
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

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







<




















|







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
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE


#--------------------------------------------------------------------
# Supply substitutes for missing POSIX header files.  Special notes:
#	- stdlib.h doesn't define strtol, strtoul, or
#	  strtod insome versions of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure
#--------------------------------------------------------------------

SC_MISSING_POSIX_HEADERS

#------------------------------------------------------------------------
# If we're using GCC, see if the compiler understands -pipe.  If so, use it.
# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    AC_CACHE_CHECK([if the compiler understands -pipe],
	tcl_cv_cc_pipe, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[fd_set readMask, writeMask;]])],
	[tcl_cv_type_fd_set=yes],
	[tcl_cv_type_fd_set=no])])
tcl_ok=$tcl_cv_type_fd_set
if test $tcl_ok = no; then
    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
	AC_EGREP_HEADER(fd_mask, sys/select.h,
	     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
    if test $tcl_cv_grep_fd_mask = present; then
	AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])







|
|
<







215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
    AC_TRY_COMPILE([#include <sys/types.h>],[fd_set readMask, writeMask;],
	tcl_cv_type_fd_set=yes, tcl_cv_type_fd_set=no)])

tcl_ok=$tcl_cv_type_fd_set
if test $tcl_ok = no; then
    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
	AC_EGREP_HEADER(fd_mask, sys/select.h,
	     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
    if test $tcl_cv_grep_fd_mask = present; then
	AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
    AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize])
fi
AC_CHECK_TYPES([blkcnt_t])
AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])

#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit data, this
#       checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

AC_FUNC_MEMCMP

#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems have no memmove
#       (we assume they have bcopy instead). {The replacement define is in
#       compat/string.h}
#--------------------------------------------------------------------

AC_CHECK_FUNC(memmove, , [
    AC_DEFINE(NO_MEMMOVE, 1, [Do we have memmove()?])
    AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ])

#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even even if
#	the original string is empty.
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strstr, [
    extern char *strstr(const char *, const char *);
    exit(strstr("\0test", "test") ? 1 : 0);
])

#--------------------------------------------------------------------
#	Check for strtoul function.  This is tricky because under some
#	versions of AIX strtoul returns an incorrect terminator
#	pointer for the string "0".
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strtoul, [
    extern unsigned long strtoul(const char *, char **, int);
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
])

#--------------------------------------------------------------------
#	Check for the strtod function.  This is tricky because in some
#	versions of Linux strtod mis-parses strings starting with "+".
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strtod, [
    extern double strtod(const char *, char **);
    char *term, *string = " +69";
    exit(strtod(string,&term) != 69 || term != string+4);
])

#--------------------------------------------------------------------
#	Under Solaris 2.4, strtod returns the wrong value for the
#	terminating character under some conditions.  Check for this







|





|
|





|
|
|







|
|



|










|










|







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize])
fi
AC_CHECK_TYPES([blkcnt_t])
AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])

#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit
#       data, this checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

AC_FUNC_MEMCMP

#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems
#       have no memmove (we assume they have bcopy instead).
#       {The replacement define is in compat/string.h}
#--------------------------------------------------------------------

AC_CHECK_FUNC(memmove, , [
    AC_DEFINE(NO_MEMMOVE, 1, [Do we have memmove()?])
    AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ])

#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even
#	even if the original string is empty.
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strstr, [
    extern int strstr();
    exit(strstr("\0test", "test") ? 1 : 0);
])

#--------------------------------------------------------------------
#	Check for strtoul function.  This is tricky because under some
#	versions of AIX strtoul returns an incorrect terminator
#	pointer for the string "0".
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strtoul, [
    extern int strtoul();
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
])

#--------------------------------------------------------------------
#	Check for the strtod function.  This is tricky because in some
#	versions of Linux strtod mis-parses strings starting with "+".
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strtod, [
    extern double strtod();
    char *term, *string = " +69";
    exit(strtod(string,&term) != 69 || term != string+4);
])

#--------------------------------------------------------------------
#	Under Solaris 2.4, strtod returns the wrong value for the
#	terminating character under some conditions.  Check for this
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339














340














341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

AC_CACHE_CHECK([for socklen_t], tcl_cv_type_socklen_t, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <sys/socket.h>
    ]], [[
    	socklen_t foo;
    ]])],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
if test $tcl_cv_type_socklen_t = no; then
    AC_DEFINE(socklen_t, int, [Define as int if socklen_t is not available])
fi

AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[














#include <stdint.h>














]])

#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which
#	is compatible with the substitute version of opendir that's
#	provided.  This version only works with V7-style directories.
#--------------------------------------------------------------------

AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H, 1, [May we include <dirent2.h>?])])

#--------------------------------------------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

AC_CACHE_CHECK([union wait], tcl_cv_union_wait, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/wait.h>]], [[
union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */
    ]])],[tcl_cv_union_wait=yes],[tcl_cv_union_wait=no])])
if test $tcl_cv_union_wait = no; then
    AC_DEFINE(NO_UNION_WAIT, 1, [Do we have a usable 'union wait'?])
fi

#--------------------------------------------------------------------
#	Check whether there is an strncasecmp function on this system.
#	This is a bit tricky because under SCO it's in -lsocket and







|


|

|




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



















|
|



|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

AC_CACHE_CHECK([for socklen_t], tcl_cv_type_socklen_t, [
    AC_TRY_COMPILE([
	#include <sys/types.h>
	#include <sys/socket.h>
    ],[
    	socklen_t foo;
    ],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
if test $tcl_cv_type_socklen_t = no; then
    AC_DEFINE(socklen_t, int, [Define as int if socklen_t is not available])
fi

AC_CHECK_TYPE([intptr_t], [
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_intptr_t" != none; then
	AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
	   type wide enough to hold a pointer.])
    fi
])
AC_CHECK_TYPE([uintptr_t], [
    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_uintptr_t" != none; then
	AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
	   type wide enough to hold a pointer.])
    fi
])

#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which
#	is compatible with the substitute version of opendir that's
#	provided.  This version only works with V7-style directories.
#--------------------------------------------------------------------

AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H, 1, [May we include <dirent2.h>?])])

#--------------------------------------------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

AC_CACHE_CHECK([union wait], tcl_cv_union_wait, [
    AC_TRY_LINK([#include <sys/types.h>
#include <sys/wait.h>], [
union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */
    ], tcl_cv_union_wait=yes, tcl_cv_union_wait=no)])
if test $tcl_cv_union_wait = no; then
    AC_DEFINE(NO_UNION_WAIT, 1, [Do we have a usable 'union wait'?])
fi

#--------------------------------------------------------------------
#	Check whether there is an strncasecmp function on this system.
#	This is a bit tricky because under SCO it's in -lsocket and
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
#	The following code checks to see whether it is possible to get
#	signed chars on this platform.  This is needed in order to
#	properly generate sign-extended ints from character values.
#--------------------------------------------------------------------

AC_C_CHAR_UNSIGNED
AC_CACHE_CHECK([signed char declarations], tcl_cv_char_signed, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	signed char *p;
	p = 0;
	]])],[tcl_cv_char_signed=yes],[tcl_cv_char_signed=no])])
if test $tcl_cv_char_signed = yes; then
    AC_DEFINE(HAVE_SIGNED_CHAR, 1, [Are characters signed?])
fi

#--------------------------------------------------------------------
#  Does putenv() copy or not?  We need to know to avoid memory leaks.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for a putenv() that copies the buffer], tcl_cv_putenv_copy, [
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
	#include <stdlib.h>
	#include <string.h>
	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
	    char *foo, *bar;
	    foo = (char *)strdup(OURVAR);
	    putenv(foo);
	    strcpy((char *)(strchr(foo, '=') + 1), "no");
	    bar = getenv("havecopy");
	    if (!strcmp(bar, "no")) {
		/* doesnt copy */
		return 0;
	    } else {
		/* does copy */
		return 1;
	    }
	}
    ]])],
    [tcl_cv_putenv_copy=no],
    [tcl_cv_putenv_copy=yes],
    [tcl_cv_putenv_copy=no])])
if test $tcl_cv_putenv_copy = yes; then
    AC_DEFINE(HAVE_PUTENV_THAT_COPIES, 1,
	[Does putenv() copy strings or incorporate them by reference?])
fi

#--------------------------------------------------------------------
# Check for support of nl_langinfo function







|


|









|

<
















|
|
|
|







434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
#	The following code checks to see whether it is possible to get
#	signed chars on this platform.  This is needed in order to
#	properly generate sign-extended ints from character values.
#--------------------------------------------------------------------

AC_C_CHAR_UNSIGNED
AC_CACHE_CHECK([signed char declarations], tcl_cv_char_signed, [
    AC_TRY_COMPILE(, [
	signed char *p;
	p = 0;
	], tcl_cv_char_signed=yes, tcl_cv_char_signed=no)])
if test $tcl_cv_char_signed = yes; then
    AC_DEFINE(HAVE_SIGNED_CHAR, 1, [Are characters signed?])
fi

#--------------------------------------------------------------------
#  Does putenv() copy or not?  We need to know to avoid memory leaks.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for a putenv() that copies the buffer], tcl_cv_putenv_copy, [
    AC_TRY_RUN([
	#include <stdlib.h>

	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
	    char *foo, *bar;
	    foo = (char *)strdup(OURVAR);
	    putenv(foo);
	    strcpy((char *)(strchr(foo, '=') + 1), "no");
	    bar = getenv("havecopy");
	    if (!strcmp(bar, "no")) {
		/* doesnt copy */
		return 0;
	    } else {
		/* does copy */
		return 1;
	    }
	}
    ],
    tcl_cv_putenv_copy=no,
    tcl_cv_putenv_copy=yes,
    tcl_cv_putenv_copy=no)])
if test $tcl_cv_putenv_copy = yes; then
    AC_DEFINE(HAVE_PUTENV_THAT_COPIES, 1,
	[Does putenv() copy strings or incorporate them by reference?])
fi

#--------------------------------------------------------------------
# Check for support of nl_langinfo function
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
AC_CHECK_FUNCS(chflags)

#--------------------------------------------------------------------
# Check for support of isnan() function or macro
#--------------------------------------------------------------------

AC_CACHE_CHECK([isnan], tcl_cv_isnan, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]], [[
isnan(0.0);			/* Generates an error if isnan is missing */
]])],[tcl_cv_isnan=yes],[tcl_cv_isnan=no])])
if test $tcl_cv_isnan = no; then
    AC_DEFINE(NO_ISNAN, 1, [Do we have a usable 'isnan'?])
fi

#--------------------------------------------------------------------
# Darwin specific API checks and defines
#--------------------------------------------------------------------







|

|







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
AC_CHECK_FUNCS(chflags)

#--------------------------------------------------------------------
# Check for support of isnan() function or macro
#--------------------------------------------------------------------

AC_CACHE_CHECK([isnan], tcl_cv_isnan, [
    AC_TRY_LINK([#include <math.h>], [
isnan(0.0);			/* Generates an error if isnan is missing */
], tcl_cv_isnan=yes, tcl_cv_isnan=no)])
if test $tcl_cv_isnan = no; then
    AC_DEFINE(NO_ISNAN, 1, [Do we have a usable 'isnan'?])
fi

#--------------------------------------------------------------------
# Darwin specific API checks and defines
#--------------------------------------------------------------------
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
	[Can this platform load code from memory?])
    AC_DEFINE(TCL_WIDE_CLICKS, 1,
	[Does this platform have wide high-resolution clicks?])
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));

		]], [[rand();]])],[tcl_cv_cc_weak_import=yes],[tcl_cv_cc_weak_import=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_weak_import = yes; then
	    AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
	fi
	AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
	    tcl_cv_cc_darwin_c_source, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>
		]], [[]])],[tcl_cv_cc_darwin_c_source=yes],[tcl_cv_cc_darwin_c_source=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_darwin_c_source = yes; then
	    AC_DEFINE(_DARWIN_C_SOURCE, 1,
		    [Are Darwin SUSv3 extensions available?])
	fi
    fi
    # Build .bundle dltest binaries in addition to .dylib
    DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
#	Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/param.h>
	    #include <sys/stat.h>
	    #include <fts.h>
	]], [[
	    char*const p[2] = {"/", NULL};
	    FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
	    FTSENT *e = fts_read(f); fts_close(f);
	]])],[tcl_cv_api_fts=yes],[tcl_cv_api_fts=no])])
if test $tcl_cv_api_fts = yes; then
    AC_DEFINE(HAVE_FTS, 1, [Do we have fts functions?])
fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style non-blocking
#	I/O (O_NONBLOCK) doesn't work or is unimplemented. On these systems
#	(mostly older ones), use the old BSD-style FIONBIO approach instead.

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

SC_BLOCKING_STYLE

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

AC_MSG_CHECKING([whether to use dll unloading])
AC_ARG_ENABLE(dll-unloading,
    AS_HELP_STRING([--enable-dll-unloading],
	[enable the 'unload' command (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test $tcl_ok = yes; then
    AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
fi
AC_MSG_RESULT([$tcl_ok])

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overridden on the configure command line either way.
#------------------------------------------------------------------------

AC_MSG_CHECKING([for timezone data])
AC_ARG_WITH(tzdata,
    AS_HELP_STRING([--with-tzdata],
	[install timezone data (default: autodetect)]),
    [tcl_ok=$withval], [tcl_ok=auto])
#
# Any directories that get added here must also be added to the
# search path in ::tcl::clock::Initialize (library/clock.tcl).
#
case $tcl_ok in







|








>
|







|









|















|



|



|



|





|
|
|
>








|










|




|







521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
	[Can this platform load code from memory?])
    AC_DEFINE(TCL_WIDE_CLICKS, 1,
	[Does this platform have wide high-resolution clicks?])
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_LINK([
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));
		], [rand();],
		tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_weak_import = yes; then
	    AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
	fi
	AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
	    tcl_cv_cc_darwin_c_source, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_COMPILE([
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>
		],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_darwin_c_source = yes; then
	    AC_DEFINE(_DARWIN_C_SOURCE, 1,
		    [Are Darwin SUSv3 extensions available?])
	fi
    fi
    # Build .bundle dltest binaries in addition to .dylib
    DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
# Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [
    AC_TRY_LINK([
	    #include <sys/param.h>
	    #include <sys/stat.h>
	    #include <fts.h>
	], [
	    char*const p[2] = {"/", NULL};
	    FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
	    FTSENT *e = fts_read(f); fts_close(f);
	], tcl_cv_api_fts=yes, tcl_cv_api_fts=no)])
if test $tcl_cv_api_fts = yes; then
    AC_DEFINE(HAVE_FTS, 1, [Do we have fts functions?])
fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
#--------------------------------------------------------------------

SC_BLOCKING_STYLE

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

AC_MSG_CHECKING([whether to use dll unloading])
AC_ARG_ENABLE(dll-unloading,
    AC_HELP_STRING([--enable-dll-unloading],
	[enable the 'unload' command (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test $tcl_ok = yes; then
    AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
fi
AC_MSG_RESULT([$tcl_ok])

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overriden on the configure command line either way.
#------------------------------------------------------------------------

AC_MSG_CHECKING([for timezone data])
AC_ARG_WITH(tzdata,
    AC_HELP_STRING([--with-tzdata],
	[install timezone data (default: autodetect)]),
    [tcl_ok=$withval], [tcl_ok=auto])
#
# Any directories that get added here must also be added to the
# search path in ::tcl::clock::Initialize (library/clock.tcl).
#
case $tcl_ok in
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

AC_ARG_ENABLE(dtrace,
    AS_HELP_STRING([--enable-dtrace],
	[build with DTrace support (default: off)]),
    [tcl_ok=$enableval], [tcl_ok=no])
if test $tcl_ok = yes; then
    AC_CHECK_HEADER(sys/sdt.h, [tcl_ok=yes], [tcl_ok=no])
fi
if test $tcl_ok = yes; then
    AC_PATH_PROG(DTRACE, dtrace,, [$PATH:/usr/sbin])







|







659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

AC_ARG_ENABLE(dtrace,
    AC_HELP_STRING([--enable-dtrace],
	[build with DTrace support (default: off)]),
    [tcl_ok=$enableval], [tcl_ok=no])
if test $tcl_ok = yes; then
    AC_CHECK_HEADER(sys/sdt.h, [tcl_ok=yes], [tcl_ok=no])
fi
if test $tcl_ok = yes; then
    AC_PATH_PROG(DTRACE, dtrace,, [$PATH:/usr/sbin])
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
AC_MSG_RESULT([$tcl_ok])

#--------------------------------------------------------------------
#  Does the C stack grow upwards or downwards? Or cross-compiling?
#--------------------------------------------------------------------

AC_CACHE_CHECK([if the C stack grows upwards in memory], tcl_cv_stack_grows_up, [
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
	int StackGrowsUp(int *parent) {
	    int here;
	    volatile int result;
	    if (parent)
		result = (&here < parent);
	    else
		result = StackGrowsUp(&here);
	    return result;
	}
	int main (int argc, char *argv[]) {
	    return StackGrowsUp(0);
	}
    ]])],[tcl_cv_stack_grows_up=yes],[tcl_cv_stack_grows_up=no],
    [tcl_cv_stack_grows_up=unknown])])
if test $tcl_cv_stack_grows_up = unknown; then
    AC_DEFINE(TCL_CROSS_COMPILE, 1, [Are we cross-compiling?])
elif test $tcl_cv_stack_grows_up = yes; then
    AC_DEFINE(TCL_STACK_GROWS_UP, 1, [The C stack grows upwards in memory.])
fi

#--------------------------------------------------------------------
# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

AC_CACHE_CHECK([whether the cpuid instruction is usable], tcl_cv_cpuid, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
	int index,regsPtr[4];
    __asm__ __volatile__("mov %%ebx, %%edi     \n\t"
                 "cpuid            \n\t"
                 "mov %%ebx, %%esi   \n\t"
                 "mov %%edi, %%ebx  \n\t"
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index) : "edi");
    ]])],[tcl_cv_cpuid=yes],[tcl_cv_cpuid=no])])
if test $tcl_cv_cpuid = yes; then
    AC_DEFINE(HAVE_CPUID, 1, [Is the cpuid instruction usable?])
fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

test -z "$TCL_LIBRARY" && TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xA000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
    AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in])
    TCL_YEAR="`date +%Y`"
fi








|












|
|











|







|



















|












|







696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
AC_MSG_RESULT([$tcl_ok])

#--------------------------------------------------------------------
#  Does the C stack grow upwards or downwards? Or cross-compiling?
#--------------------------------------------------------------------

AC_CACHE_CHECK([if the C stack grows upwards in memory], tcl_cv_stack_grows_up, [
    AC_TRY_RUN([
	int StackGrowsUp(int *parent) {
	    int here;
	    volatile int result;
	    if (parent)
		result = (&here < parent);
	    else
		result = StackGrowsUp(&here);
	    return result;
	}
	int main (int argc, char *argv[]) {
	    return StackGrowsUp(0);
	}
    ], tcl_cv_stack_grows_up=yes, tcl_cv_stack_grows_up=no,
    tcl_cv_stack_grows_up=unknown)])
if test $tcl_cv_stack_grows_up = unknown; then
    AC_DEFINE(TCL_CROSS_COMPILE, 1, [Are we cross-compiling?])
elif test $tcl_cv_stack_grows_up = yes; then
    AC_DEFINE(TCL_STACK_GROWS_UP, 1, [The C stack grows upwards in memory.])
fi

#--------------------------------------------------------------------
# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

AC_CACHE_CHECK([whether the cpuid instruction is usable], tcl_cv_cpuid, [
    AC_TRY_LINK(, [
	int index,regsPtr[4];
    __asm__ __volatile__("mov %%ebx, %%edi     \n\t"
                 "cpuid            \n\t"
                 "mov %%ebx, %%esi   \n\t"
                 "mov %%edi, %%ebx  \n\t"
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index) : "edi");
    ], tcl_cv_cpuid=yes, tcl_cv_cpuid=no)])
if test $tcl_cv_cpuid = yes; then
    AC_DEFINE(HAVE_CPUID, 1, [Is the cpuid instruction usable?])
fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
    AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in])
    TCL_YEAR="`date +%Y`"
fi

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)/TclTOC.html"'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh







|







797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------








|

|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
    TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

913
914
915
916
917
918
919
920
921
922
923
AC_CONFIG_FILES([
    Makefile:../unix/Makefile.in
    dltest/Makefile:../unix/dltest/Makefile.in
    tclConfig.sh:../unix/tclConfig.sh.in
    tcl.pc:../unix/tcl.pc.in
])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf
dnl End:







<
<
<
<
939
940
941
942
943
944
945




AC_CONFIG_FILES([
    Makefile:../unix/Makefile.in
    dltest/Makefile:../unix/dltest/Makefile.in
    tclConfig.sh:../unix/tclConfig.sh.in
    tcl.pc:../unix/tcl.pc.in
])
AC_OUTPUT




Changes to unix/dltest/pkga.c.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkga_EqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkga_QuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkga_EqObjCmd --
 *
 *	This procedure is invoked to process the "pkga_eq" Tcl command. It







|

|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkga_EqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
static int    Pkga_QuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkga_EqObjCmd --
 *
 *	This procedure is invoked to process the "pkga_eq" Tcl command. It
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 */

static int
Pkga_EqObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;
    const char *str1, *str2;
    int len1, len2;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);







|


|

<







40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
 */

static int
Pkga_EqObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    int result;
    CONST char *str1, *str2;
    int len1, len2;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
 */

static int
Pkga_QuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[1]);
    return TCL_OK;
}







|

<
<







84
85
86
87
88
89
90
91
92


93
94
95
96
97
98
99
 */

static int
Pkga_QuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument strings. */
{


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[1]);
    return TCL_OK;
}
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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkga_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkga", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkga_eq", Pkga_EqObjCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "pkga_quote", Pkga_QuoteObjCmd, NULL,
	    NULL);
    return TCL_OK;
}







|






|


|



|
>
|
|


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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkga_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkga", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkga_eq", Pkga_EqObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "pkga_quote", Pkga_QuoteObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgb.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgb_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgb_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgb_sub" Tcl command. It







|

|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgb_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
static int    Pkgb_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgb_sub" Tcl command. It
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#endif

static int
Pkgb_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {







|


<







44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
#endif

static int
Pkgb_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    int first, second;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
 */

static int
Pkgb_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    return Tcl_EvalEx(interp, "list unsafe command invoked", -1, TCL_EVAL_GLOBAL);
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.







|

<
<
<
<


|







85
86
87
88
89
90
91
92
93




94
95
96
97
98
99
100
101
102
103
 */

static int
Pkgb_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{




    return Tcl_EvalEx(interp, "list unsafe command invoked", -1, TCL_EVAL_GLOBAL);
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.
120
121
122
123
124
125
126

127
128


129
130
131
132
133

134

135
136
137
138
139
140
141
Pkgb_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {

	return TCL_ERROR;
    }


    code = Tcl_PkgProvide(interp, "pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "pkgb_unsafe", Pkgb_UnsafeObjCmd, NULL, NULL);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_SafeInit --







>
|
|
>
>
|



|
>
|
>







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
140
141
Pkgb_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	if (Tcl_InitStubs(interp, "8.4-", 0) == NULL) {
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
    }
    code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "pkgb_unsafe", Pkgb_UnsafeObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_SafeInit --
156
157
158
159
160
161
162

163
164


165
166
167
168
169

170
171
Pkgb_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {

	return TCL_ERROR;
    }


    code = Tcl_PkgProvide(interp, "pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);

    return TCL_OK;
}







>
|
|
>
>
|



|
>


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
Pkgb_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	if (Tcl_InitStubs(interp, "8.4-", 0) == NULL) {
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
    }
    code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, (ClientData) 0,
	    (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgc.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgc_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgc_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgc_sub" Tcl command. It







|

|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgc_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
static int    Pkgc_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgc_sub" Tcl command. It
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 */

static int
Pkgc_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {







|


<







40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
 */

static int
Pkgc_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    int first, second;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 */

static int
Pkgc_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|

<
<
<
<







78
79
80
81
82
83
84
85
86




87
88
89
90
91
92
93
 */

static int
Pkgc_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{




    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgc_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "pkgc_unsafe", Pkgc_UnsafeObjCmd, NULL,
	    NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgc_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);

    return TCL_OK;
}







|






|


|



|
>
|
|




















|






|


|



|
>


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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgc_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "pkgc_unsafe", Pkgc_UnsafeObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgc_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, (ClientData) 0,
	    (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgd.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgd_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgd_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgd_sub" Tcl command. It







|

|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgd_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
static int    Pkgd_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgd_sub" Tcl command. It
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 */

static int
Pkgd_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {







|


<







40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
 */

static int
Pkgd_SubObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    int first, second;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 */

static int
Pkgd_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|

<
<
<
<







78
79
80
81
82
83
84
85
86




87
88
89
90
91
92
93
 */

static int
Pkgd_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{




    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgd_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "pkgd_unsafe", Pkgd_UnsafeObjCmd, NULL,
	    NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgd_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);

    return TCL_OK;
}







|






|


|



|
>
|
|




















|






|


|



|
>


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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgd_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "pkgd_unsafe", Pkgd_UnsafeObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgd_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, (ClientData) 0,
	    (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkge.c.

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
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"


/*
 *----------------------------------------------------------------------
 *
 * Pkge_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.
 *
 * Results:
 *	Returns TCL_ERROR and leaves an error message in interp->result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkge_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    static const char script[] = "if 44 {open non_existent}";

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    return Tcl_EvalEx(interp, script, -1, 0);
}







>


















|




|

|


|

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
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"


/*
 *----------------------------------------------------------------------
 *
 * Pkge_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.
 *
 * Results:
 *	Returns TCL_ERROR and leaves an error message in interp->result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkge_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    static char script[] = "if 44 {open non_existent}";

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    return Tcl_Eval(interp, script);
}

Changes to unix/dltest/pkgua.c.

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
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    PkguaEqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    PkguaQuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 * In the following hash table we are going to store a struct that holds all
 * the command tokens created by Tcl_CreateObjCommand in an interpreter,
 * indexed by the interpreter. In this way, we can find which command tokens
 * we have registered in a specific interpreter, in order to unload them. We
 * need to keep the various command tokens we have registered, as they are the
 * only safe way to unregister our registered commands, even if they have been
 * renamed.
 *
 * Note that this code is utterly single-threaded.
 */

static Tcl_HashTable interpTokenMap;
static int interpTokenMapInitialised = 0;
#define MAX_REGISTERED_COMMANDS 2


static void
PkguaInitTokensHashTable(void)
{
    if (interpTokenMapInitialised) {
	return;
    }
    Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
    interpTokenMapInitialised = 1;
}

static void
PkguaFreeTokensHashTable(void)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;

    for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {







|

|

















>










|







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
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    PkguaEqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
static int    PkguaQuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

/*
 * In the following hash table we are going to store a struct that holds all
 * the command tokens created by Tcl_CreateObjCommand in an interpreter,
 * indexed by the interpreter. In this way, we can find which command tokens
 * we have registered in a specific interpreter, in order to unload them. We
 * need to keep the various command tokens we have registered, as they are the
 * only safe way to unregister our registered commands, even if they have been
 * renamed.
 *
 * Note that this code is utterly single-threaded.
 */

static Tcl_HashTable interpTokenMap;
static int interpTokenMapInitialised = 0;
#define MAX_REGISTERED_COMMANDS 2


static void
PkguaInitTokensHashTable(void)
{
    if (interpTokenMapInitialised) {
	return;
    }
    Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
    interpTokenMapInitialised = 1;
}

void
PkguaFreeTokensHashTable(void)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;

    for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    int newEntry;
    Tcl_Command *cmdTokens;
    Tcl_HashEntry *entryPtr =
	    Tcl_CreateHashEntry(&interpTokenMap, (char *) interp, &newEntry);

    if (newEntry) {
	cmdTokens = (Tcl_Command *)
		Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS));
	for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS ; ++newEntry) {
	    cmdTokens[newEntry] = NULL;
	}
	Tcl_SetHashValue(entryPtr, (ClientData) cmdTokens);
    } else {
	cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
    }
    return cmdTokens;







|
|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    int newEntry;
    Tcl_Command *cmdTokens;
    Tcl_HashEntry *entryPtr =
	    Tcl_CreateHashEntry(&interpTokenMap, (char *) interp, &newEntry);

    if (newEntry) {
	cmdTokens = (Tcl_Command *)
		Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS+1));
	for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS+1 ; ++newEntry) {
	    cmdTokens[newEntry] = NULL;
	}
	Tcl_SetHashValue(entryPtr, (ClientData) cmdTokens);
    } else {
	cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
    }
    return cmdTokens;
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
 */

static int
PkguaEqObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;
    const char *str1, *str2;
    int len1, len2;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);







|


|

<







116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
 */

static int
PkguaEqObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    int result;
    CONST char *str1, *str2;
    int len1, len2;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 */

static int
PkguaQuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[1]);
    return TCL_OK;
}







|

<
<







160
161
162
163
164
165
166
167
168


169
170
171
172
173
174
175
 */

static int
PkguaQuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument strings. */
{


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[1]);
    return TCL_OK;
}
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgua_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;
    Tcl_Command *cmdTokens;

    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Initialize our Hash table, where we store the registered command tokens
     * for each interpreter.
     */

    PkguaInitTokensHashTable();

    code = Tcl_PkgProvide(interp, "pkgua", "1.0");
    if (code != TCL_OK) {
	return code;
    }

    Tcl_SetVar2(interp, "::pkgua_loaded", NULL, ".", TCL_APPEND_VALUE);

    cmdTokens = PkguaInterpToTokens(interp);
    cmdTokens[0] =
	    Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd,
		    NULL, NULL);
    cmdTokens[1] =
	    Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
		    NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgua_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgua_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    return Pkgua_Init(interp);
}








|




|


|




|





|




|


|

|
|

|




















|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgua_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code, cmdIndex = 0;
    Tcl_Command *cmdTokens;

    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Initialise our Hash table, where we store the registered command tokens
     * for each interpreter.
     */

    PkguaInitTokensHashTable();

    code = Tcl_PkgProvide(interp, "Pkgua", "1.0");
    if (code != TCL_OK) {
	return code;
    }

    Tcl_SetVar(interp, "::pkgua_loaded", ".", TCL_APPEND_VALUE);

    cmdTokens = PkguaInterpToTokens(interp);
    cmdTokens[cmdIndex++] =
	    Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd,
		    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    cmdTokens[cmdIndex++] =
	    Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
		    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgua_SafeInit --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to a safe interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgua_SafeInit(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    return Pkgua_Init(interp);
}

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgua_Unload(
    Tcl_Interp *interp,		/* Interpreter from which the package is to be
				 * unloaded. */
    int flags)			/* Flags passed by the unloading mechanism */
{
    int code, cmdIndex;
    Tcl_Command *cmdTokens = PkguaInterpToTokens(interp);

    for (cmdIndex=0 ; cmdIndex<MAX_REGISTERED_COMMANDS ; cmdIndex++) {
	if (cmdTokens[cmdIndex] == NULL) {
	    continue;
	}
	code = Tcl_DeleteCommandFromToken(interp, cmdTokens[cmdIndex]);
	if (code != TCL_OK) {
	    return code;
	}
    }

    PkguaDeleteTokens(interp);

    Tcl_SetVar2(interp, "::pkgua_detached", NULL, ".", TCL_APPEND_VALUE);

    if (flags == TCL_UNLOAD_DETACH_FROM_PROCESS) {
	/*
	 * Tcl is ready to detach this library from the running application.
	 * We should free all the memory that is not related to any
	 * interpreter.
	 */

	PkguaFreeTokensHashTable();
	Tcl_SetVar2(interp, "::pkgua_unloaded", NULL, ".", TCL_APPEND_VALUE);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|




















|









|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgua_Unload(
    Tcl_Interp *interp,		/* Interpreter from which the package is to be
				 * unloaded. */
    int flags)			/* Flags passed by the unloading mechanism */
{
    int code, cmdIndex;
    Tcl_Command *cmdTokens = PkguaInterpToTokens(interp);

    for (cmdIndex=0 ; cmdIndex<MAX_REGISTERED_COMMANDS ; cmdIndex++) {
	if (cmdTokens[cmdIndex] == NULL) {
	    continue;
	}
	code = Tcl_DeleteCommandFromToken(interp, cmdTokens[cmdIndex]);
	if (code != TCL_OK) {
	    return code;
	}
    }

    PkguaDeleteTokens(interp);

    Tcl_SetVar(interp, "::pkgua_detached", ".", TCL_APPEND_VALUE);

    if (flags == TCL_UNLOAD_DETACH_FROM_PROCESS) {
	/*
	 * Tcl is ready to detach this library from the running application.
	 * We should free all the memory that is not related to any
	 * interpreter.
	 */

	PkguaFreeTokensHashTable();
	Tcl_SetVar(interp, "::pkgua_unloaded", ".", TCL_APPEND_VALUE);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkgua_SafeUnload(
    Tcl_Interp *interp,		/* Interpreter from which the package is to be
				 * unloaded. */
    int flags)			/* Flags passed by the unloading mechanism */
{
    return Pkgua_Unload(interp, flags);
}







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Pkgua_SafeUnload(
    Tcl_Interp *interp,		/* Interpreter from which the package is to be
				 * unloaded. */
    int flags)			/* Flags passed by the unloading mechanism */
{
    return Pkgua_Unload(interp, flags);
}

Changes to unix/installManPage.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

ManPage=$1
Dir=$2
if test -f $ManPage ; then : ; else
    echo "source manual page file must exist"
    exit 1
fi
if test -d "$Dir" ; then : ; else
    echo "target directory must exist"
    exit 1
fi
test -z "$SymOrLoc" && SymOrLoc="$Dir/"

########################################################################
### Extract Target Names from Manual Page







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

ManPage=$1
Dir=$2
if test -f $ManPage ; then : ; else
    echo "source manual page file must exist"
    exit 1
fi
if test -d $Dir ; then : ; else
    echo "target directory must exist"
    exit 1
fi
test -z "$SymOrLoc" && SymOrLoc="$Dir/"

########################################################################
### Extract Target Names from Manual Page
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
120
121
122
123
124
    *.1) Section=1 ;;
    *.3) Section=3 ;;
    *.n) Section=n ;;
    *)	echo "unknown section for $ManPage"
	exit 2 ;;
esac

Name=`basename $ManPage .$Section`
SrcDir=`dirname $ManPage`

########################################################################
### Process Page to Create Target Pages
###

Specials="DString Thread Notifier RegExp library packagens pkgMkIndex safesock FindPhoto FontId MeasureChar"
for n in $Specials; do
    if [ "$Name" = "$n" ] ; then
	Names="$n $Names"
    fi
done

First=""
for Target in $Names; do
    Target=$Target.$Section$Suffix
    rm -f "$Dir/$Target" "$Dir/$Target.*"
    if test -z "$First" ; then
	First=$Target
	sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
	    $ManPage > "$Dir/$First"
	chmod 644 "$Dir/$First"
	$Gzip "$Dir/$First"
    else
	ln $SymOrLoc"$First$Gz" "$Dir/$Target$Gz"
    fi
done

########################################################################
exit 0







<






<
<
<
<
<
<
<



|



|
|
|

|





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
    *.1) Section=1 ;;
    *.3) Section=3 ;;
    *.n) Section=n ;;
    *)	echo "unknown section for $ManPage"
	exit 2 ;;
esac


SrcDir=`dirname $ManPage`

########################################################################
### Process Page to Create Target Pages
###








First=""
for Target in $Names; do
    Target=$Target.$Section$Suffix
    rm -f $Dir/$Target $Dir/$Target.*
    if test -z "$First" ; then
	First=$Target
	sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
	    $ManPage > $Dir/$First
	chmod 644 $Dir/$First
	$Gzip $Dir/$First
    else
	ln $SymOrLoc$First$Gz $Dir/$Target$Gz
    fi
done

########################################################################
exit 0

Changes to unix/tcl.m4.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )







|

|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tcl8.5 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"







<







90
91
92
93
94
95
96

97
98
99
100
101
102
103
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \

			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tcl8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )







|

|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tk8.5 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"







<







223
224
225
226
227
228
229

230
231
232
233
234
235
236
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \

			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.5 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
275
276
277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE

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

AC_DEFUN([SC_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])







|



>







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Subst the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
#	a Tcl shell that has been installed from the Tcl build directory.
#	If a Tcl shell can't be located on the PATH, then TCLSH_PROG will
#	be set to "". Extensions should take care not to create Makefile
#	rules that are run by default and depend on TCLSH_PROG. An
#	extension can't assume that an executable Tcl shell exists at
#	build time.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([SC_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])
    AC_CACHE_VAL(ac_cv_path_tclsh, [
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`







|


|
|







441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
#	a Tcl shell that has been installed from the Tcl build directory.
#	If a Tcl shell can't be located on the PATH, then TCLSH_PROG will
#	be set to "". Extensions should take care not to create Makefile
#	rules that are run by default and depend on TCLSH_PROG. An
#	extension can't assume that an executable Tcl shell exists at
#	build time.
#
# Arguments
#	none
#
# Results
#	Subst's the following values:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([SC_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])
    AC_CACHE_VAL(ac_cv_path_tclsh, [
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
#	Determine the fully qualified path name of the tclsh executable
#	in the Tcl build directory. This macro will correctly determine
#	the name of the tclsh executable even if tclsh has not yet
#	been built in the build directory. The build tclsh must be used
#	when running tests from an extension build directory. It is not
#	correct to use the TCLSH_PROG in cases like this.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following values:
#		BUILD_TCLSH
#------------------------------------------------------------------------

AC_DEFUN([SC_BUILD_TCLSH], [
    AC_MSG_CHECKING([for tclsh in Tcl build directory])
    BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh
    AC_MSG_RESULT([$BUILD_TCLSH])







|


|
|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
#	Determine the fully qualified path name of the tclsh executable
#	in the Tcl build directory. This macro will correctly determine
#	the name of the tclsh executable even if tclsh has not yet
#	been built in the build directory. The build tclsh must be used
#	when running tests from an extension build directory. It is not
#	correct to use the TCLSH_PROG in cases like this.
#
# Arguments
#	none
#
# Results
#	Subst's the following values:
#		BUILD_TCLSH
#------------------------------------------------------------------------

AC_DEFUN([SC_BUILD_TCLSH], [
    AC_MSG_CHECKING([for tclsh in Tcl build directory])
    BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh
    AC_MSG_RESULT([$BUILD_TCLSH])
526
527
528
529
530
531
532
533
534
535








536
537
538
539
540
541
542
#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AS_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])








    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])







|


>
>
>
>
>
>
>
>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
#		FRAMEWORK_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_FRAMEWORK], [
    if test "`uname -s`" = "Darwin" ; then
	AC_MSG_CHECKING([how to package libraries])
	AC_ARG_ENABLE(framework,
	    AS_HELP_STRING([--enable-framework],
		[package shared libraries in MacOSX frameworks (default: off)]),
	    [enable_framework=$enableval], [enable_framework=no])
	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
		enable_framework=no
	    fi







|







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
#		FRAMEWORK_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_FRAMEWORK], [
    if test "`uname -s`" = "Darwin" ; then
	AC_MSG_CHECKING([how to package libraries])
	AC_ARG_ENABLE(framework,
	    AC_HELP_STRING([--enable-framework],
		[package shared libraries in MacOSX frameworks (default: off)]),
	    [enable_framework=$enableval], [enable_framework=no])
	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
		enable_framework=no
	    fi
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
#		_REENTRANT
#		_THREAD_SAFE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AS_HELP_STRING([--enable-threads],
	    [build with threads (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])

    if test "${TCL_THREADS}" = 1; then
	tcl_threaded_core=1;
    fi








|







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
#		_REENTRANT
#		_THREAD_SAFE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])

    if test "${TCL_THREADS}" = 1; then
	tcl_threaded_core=1;
    fi

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
#				always blank now.
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SYMBOLS], [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AS_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'







|







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
#				always blank now.
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SYMBOLS], [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
818
819
820
821
822
823
824

825
826
827
828
829
830
831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
# Results:
#
#	Adds the following arguments to configure:
#		--enable-langinfo=yes|no (default is yes)
#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.

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

AC_DEFUN([SC_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AS_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [

	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]], [[nl_langinfo(CODESET);]])],[tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
    fi







>




|










>
|







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
# Results:
#
#	Adds the following arguments to configure:
#		--enable-langinfo=yes|no (default is yes)
#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [
	    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
		    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
    fi
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
#			according to the user's selection.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_MANPAGES], [
    AC_MSG_CHECKING([whether to use symlinks for manpages])
    AC_ARG_ENABLE(man-symlinks,
	AS_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	[test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"],
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_MSG_CHECKING([whether to compress the manpages])
    AC_ARG_ENABLE(man-compression,
	AS_HELP_STRING([--enable-man-compression=PROG],
	    [compress the manpages with PROG (default: off)]),
	[case $enableval in
	    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac],
	[enableval="no"])
    AC_MSG_RESULT([$enableval])
    if test "$enableval" != "no"; then
	AC_MSG_CHECKING([for compressed file suffix])
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	AC_MSG_RESULT([$Z])
    fi

    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
    AC_ARG_ENABLE(man-suffix,
	AS_HELP_STRING([--enable-man-suffix=STRING],
	    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
	[case $enableval in
	    yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac],
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_SUBST(MAN_FLAGS)
])

#--------------------------------------------------------------------
# SC_CONFIG_SYSTEM







|

|
|




|






|













|






|







882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
#			according to the user's selection.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_MANPAGES], [
    AC_MSG_CHECKING([whether to use symlinks for manpages])
    AC_ARG_ENABLE(man-symlinks,
	AC_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
	enableval="no")
    AC_MSG_RESULT([$enableval])

    AC_MSG_CHECKING([whether to compress the manpages])
    AC_ARG_ENABLE(man-compression,
	AC_HELP_STRING([--enable-man-compression=PROG],
	    [compress the manpages with PROG (default: off)]),
	[case $enableval in
	    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac],
	enableval="no")
    AC_MSG_RESULT([$enableval])
    if test "$enableval" != "no"; then
	AC_MSG_CHECKING([for compressed file suffix])
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	AC_MSG_RESULT([$Z])
    fi

    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
    AC_ARG_ENABLE(man-suffix,
	AC_HELP_STRING([--enable-man-suffix=STRING],
	    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
	[case $enableval in
	    yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac],
	enableval="no")
    AC_MSG_RESULT([$enableval])

    AC_SUBST(MAN_FLAGS)
])

#--------------------------------------------------------------------
# SC_CONFIG_SYSTEM
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi
    ])
    system=$tcl_cv_sys_version
])

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







<
<
<







961
962
963
964
965
966
967



968
969
970
971
972
973
974

		if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
		    tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid`
		fi
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi



	    fi
	fi
    ])
    system=$tcl_cv_sys_version
])

#--------------------------------------------------------------------
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

AC_DEFUN([SC_CONFIG_CFLAGS], [

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AS_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AS_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}]], [[f();]])],
	    [tcl_cv_cc_visibility_hidden=yes],
	    [tcl_cv_cc_visibility_hidden=no])
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AS_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # Step 1: set the variable "system" to hold the name and version number
    # for the system.








|








|












|

<
|
|











|







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

AC_DEFUN([SC_CONFIG_CFLAGS], [

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_TRY_LINK([
	    extern __attribute__((__visibility__("hidden"))) void f(void);

	    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
	    tcl_cv_cc_visibility_hidden=no)
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # Step 1: set the variable "system" to hold the name and version number
    # for the system.

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
    UNSHARED_LIB_SUFFIX=""
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    CFLAGS_OPTIMIZE=-O
    AS_IF([test "$GCC" = yes], [
	CFLAGS_WARNING="-Wall -Wpointer-arith"
    ], [CFLAGS_WARNING=""])
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    LDAIX_SRC=""







|







1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
    UNSHARED_LIB_SUFFIX=""
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    CFLAGS_OPTIMIZE=-O
    AS_IF([test "$GCC" = yes], [
	CFLAGS_WARNING="-Wall"
    ], [CFLAGS_WARNING=""])
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    LDAIX_SRC=""
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*|MINGW32_*|MSYS_*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o tclWinError.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		]], [[]])],
		[ac_cv_cygwin=no],
		[ac_cv_cygwin=yes])
	    )
	    if test "$ac_cv_cygwin" = "no"; then
		AC_MSG_ERROR([${CC} is not a cygwin compiler.])
	    fi
	    if test "x${TCL_THREADS}" = "x0"; then
		AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
	    fi







|












|



|
|
|







1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*|MINGW32*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o tclWinError.o"
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_TRY_COMPILE([
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		], [],
		ac_cv_cygwin=no,
		ac_cv_cygwin=yes)
	    )
	    if test "$ac_cv_cygwin" = "no"; then
		AC_MSG_ERROR([${CC} is not a cygwin compiler.])
	    fi
	    if test "x${TCL_THREADS}" = "x0"; then
		AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
	    fi
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-lroot"
	    AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible
	    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])







|







1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-lroot"
	    AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible
	    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no])
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])








|











|







1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])

1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
	    arch=`arch -s`
	    case "$arch" in
	    vax)
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""

		;;
	    *)
		case "$arch" in
		alpha|sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
		    SHLIB_CFLAGS="-fpic"
		    ;;
		esac
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
		;;
	    esac
	    case "$arch" in
	    vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    sh)







>


















|







1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
	    arch=`arch -s`
	    case "$arch" in
	    vax)
		# Equivalent using configure option --disable-load
		# Step 4 will set the necessary variables
		DL_OBJS=""
		SHLIB_LD_LIBS=""
		LDFLAGS=""
		;;
	    *)
		case "$arch" in
		alpha|sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC"
		    ;;
		*)
		    SHLIB_CFLAGS="-fpic"
		    ;;
		esac
		SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		LDFLAGS="-Wl,-export-dynamic"
		;;
	    esac
	    case "$arch" in
	    vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    sh)
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567

1568
1569
1570
1571
1572
1573
1574
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	DragonFly-*|FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""

	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"







|














|







>







1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_ppc64=yes],
				    [tcl_cv_cc_arch_ppc64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_x86_64=yes],
				    [tcl_cv_cc_arch_x86_64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_single_module=yes],[tcl_cv_ld_single_module=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    DL_LIBS=""
	    # Don't use -prebind when building for Mac OS X 10.4 or later only:
	    AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
		"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
		LDFLAGS="$LDFLAGS -prebind"])
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],
			[tcl_cv_ld_search_paths_first=yes],
			[tcl_cv_ld_search_paths_first=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    AC_MSG_CHECKING([whether to use CoreFoundation])
	    AC_ARG_ENABLE(corefoundation,
		AS_HELP_STRING([--enable-corefoundation],
		    [use CoreFoundation API on MacOSX (default: on)]),
		[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
	    AC_MSG_RESULT([$tcl_corefoundation])
	    AS_IF([test $tcl_corefoundation = yes], [
		AC_CACHE_CHECK([for CoreFoundation.framework],
			tcl_cv_lib_corefoundation, [
		    hold_libs=$LIBS
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    # On Tiger there is no 64-bit CF, so remove 64-bit
			    # archs from CFLAGS et al. while testing for
			    # presence of CF. 64-bit CF is disabled in
			    # tclUnixPort.h if necessary.
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
			done])
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],
			[[CFBundleRef b = CFBundleGetMainBundle();]])],
			[tcl_cv_lib_corefoundation=yes],
			[tcl_cv_lib_corefoundation=no])
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done])
		    LIBS=$hold_libs])
		AS_IF([test $tcl_cv_lib_corefoundation = yes], [
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_DEFINE(HAVE_COREFOUNDATION, 1,
			[Do we have access to Darwin CoreFoundation.framework?])
		], [tcl_corefoundation=no])
		AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
		    AC_CACHE_CHECK([for 64-bit CoreFoundation],
			    tcl_cv_lib_corefoundation_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],
			    [[CFBundleRef b = CFBundleGetMainBundle();]])],
			    [tcl_cv_lib_corefoundation_64=yes],
			    [tcl_cv_lib_corefoundation_64=no])
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		    AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
			AC_DEFINE(NO_COREFOUNDATION_64, 1,
			    [Is Darwin CoreFoundation unavailable for 64-bit?])
                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"







<
|
|










<
|
|


















|
















<
|
|
















|
















|
|
|
|
















|
|
|
|







1605
1606
1607
1608
1609
1610
1611

1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660

1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"

			    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
				    tcl_cv_cc_arch_ppc64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"

			    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
				    tcl_cv_cc_arch_x86_64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    DL_LIBS=""
	    # Don't use -prebind when building for Mac OS X 10.4 or later only:
	    AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
		"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
		LDFLAGS="$LDFLAGS -prebind"])
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"

		AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
			tcl_cv_ld_search_paths_first=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    AC_MSG_CHECKING([whether to use CoreFoundation])
	    AC_ARG_ENABLE(corefoundation,
		AC_HELP_STRING([--enable-corefoundation],
		    [use CoreFoundation API on MacOSX (default: on)]),
		[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
	    AC_MSG_RESULT([$tcl_corefoundation])
	    AS_IF([test $tcl_corefoundation = yes], [
		AC_CACHE_CHECK([for CoreFoundation.framework],
			tcl_cv_lib_corefoundation, [
		    hold_libs=$LIBS
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    # On Tiger there is no 64-bit CF, so remove 64-bit
			    # archs from CFLAGS et al. while testing for
			    # presence of CF. 64-bit CF is disabled in
			    # tclUnixPort.h if necessary.
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
			done])
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
			[CFBundleRef b = CFBundleGetMainBundle();],
			tcl_cv_lib_corefoundation=yes,
			tcl_cv_lib_corefoundation=no)
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done])
		    LIBS=$hold_libs])
		AS_IF([test $tcl_cv_lib_corefoundation = yes], [
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_DEFINE(HAVE_COREFOUNDATION, 1,
			[Do we have access to Darwin CoreFoundation.framework?])
		], [tcl_corefoundation=no])
		AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
		    AC_CACHE_CHECK([for 64-bit CoreFoundation],
			    tcl_cv_lib_corefoundation_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
			    [CFBundleRef b = CFBundleGetMainBundle();],
			    tcl_cv_lib_corefoundation_64=yes,
			    tcl_cv_lib_corefoundation_64=no)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		    AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
			AC_DEFINE(NO_COREFOUNDATION_64, 1,
			    [Is Darwin CoreFoundation unavailable for 64-bit?])
                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    AS_IF([test "$GCC" = yes], [
		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
	    ], [
		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
	    ])
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""







|
|

|
|







1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    AS_IF([test "$GCC" = yes], [
	    	SHLIB_CFLAGS="-fPIC -melf"
	    	LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
	    ], [
	    	SHLIB_CFLAGS="-Kpic -belf"
	    	LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
	    ])
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
	    #--------------------------------------------------------------------
	    # On Solaris 5.x i386 with the sunpro compiler we need to link
	    # with sunmath to get floating point rounding control
	    #--------------------------------------------------------------------
	    AS_IF([test "$GCC" = yes],[use_sunmath=no],[
		arch=`isainfo`
		AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])
		AS_IF([test "$arch" = "amd64 i386" -o "$arch" = "i386"], [
			AC_MSG_RESULT([yes])
			MATH_LIBS="-lsunmath $MATH_LIBS"
			AC_CHECK_HEADER(sunmath.h)
			use_sunmath=yes
			], [
			AC_MSG_RESULT([no])
			use_sunmath=no







|







1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
	    #--------------------------------------------------------------------
	    # On Solaris 5.x i386 with the sunpro compiler we need to link
	    # with sunmath to get floating point rounding control
	    #--------------------------------------------------------------------
	    AS_IF([test "$GCC" = yes],[use_sunmath=no],[
		arch=`isainfo`
		AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])
		AS_IF([test "$arch" = "amd64 i386"], [
			AC_MSG_RESULT([yes])
			MATH_LIBS="-lsunmath $MATH_LIBS"
			AC_CHECK_HEADER(sunmath.h)
			use_sunmath=yes
			], [
			AC_MSG_RESULT([no])
			use_sunmath=no
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
		    ], [AS_IF([test "$arch" = "amd64 i386"], [
			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
		    ])])
		])
	    ], [
		AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text])
		case $system in
		    SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]])
			SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
		    *)
			SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ])
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no])
	        LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;







|




















|







1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
		    ], [AS_IF([test "$arch" = "amd64 i386"], [
			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
		    ])])
		])
	    ], [
		AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text])
		case $system in
		    SunOS-5.[[1-9]][[0-9]]*)
			SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
		    *)
			SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ])
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
	        LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Step 4: disable dynamic loading if requested via a command-line switch.

    AC_ARG_ENABLE(load,
	AS_HELP_STRING([--enable-load],
	    [allow dynamic loading and "load" command (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
    AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])

    AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
	AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
	SHLIB_CFLAGS=""







|







2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Step 4: disable dynamic loading if requested via a command-line switch.

    AC_ARG_ENABLE(load,
	AC_HELP_STRING([--enable-load],
	    [allow dynamic loading and "load" command (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
    AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])

    AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
	AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
	SHLIB_CFLAGS=""
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    IRIX*) ;;
	    NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])







|

|







2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*) ;;
	    IRIX*) ;;
	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
2106
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ]])],
	    [tcl_cv_cast_to_union=yes],
	    [tcl_cv_cast_to_union=no])
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

    # FIXME: This subst was left in only because the TCL_DL_LIBS







|
>


|
|
|







2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

    # FIXME: This subst was left in only because the TCL_DL_LIBS
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
#		USE_SGTTY
#
#--------------------------------------------------------------------

AC_DEFUN([SC_SERIAL_PORT], [
    AC_CHECK_HEADERS(sys/modem.h)
    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termios.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    if test $tcl_cv_api_serial = no ; then
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termio.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sgtty.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termios.h>
#include <errno.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no; then
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <termio.h>
#include <errno.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
    }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no])
    fi
    if test $tcl_cv_api_serial = no; then
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sgtty.h>
#include <errno.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=none],[tcl_cv_api_serial=none])
    fi])
    case $tcl_cv_api_serial in
	termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
	termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
	sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
    esac
])







|










|

|









|


|










|


|












|


|











|


|












|







2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
#		USE_SGTTY
#
#--------------------------------------------------------------------

AC_DEFUN([SC_SERIAL_PORT], [
    AC_CHECK_HEADERS(sys/modem.h)
    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
    AC_TRY_RUN([
#include <termios.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termio.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <sgtty.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termios.h>
#include <errno.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <termio.h>
#include <errno.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <sgtty.h>
#include <errno.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
    fi])
    case $tcl_cv_api_serial in
	termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
	termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
	sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
    esac
])
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
#		NO_VALUES_H
#		HAVE_LIMITS_H or NO_LIMITS_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H

#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
]])],[tcl_cv_dirent_h=yes],[tcl_cv_dirent_h=no])])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])







>






|
|

















|







2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
#		NO_VALUES_H
#		HAVE_LIMITS_H or NO_LIMITS_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#
#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_CHECK_HEADERS([sys/param.h])
])

#--------------------------------------------------------------------
# SC_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff







|







2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_HAVE_HEADERS(sys/param.h)
])

#--------------------------------------------------------------------
# SC_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
#--------------------------------------------------------------------

AC_DEFUN([SC_PATH_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[],[not_really_there="yes"])
	else
	    if test ! -r $x_includes/X11/Xlib.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[found_xincludes="yes"],[found_xincludes="no"])
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Xlib.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"







|









|







2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
#--------------------------------------------------------------------

AC_DEFUN([SC_PATH_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
	else
	    if test ! -r $x_includes/X11/Xlib.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Xlib.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
AC_DEFUN([SC_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME

    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; tm.tm_tzadj;]])],
	    [tcl_cv_member_tm_tzadj=yes],
	    [tcl_cv_member_tm_tzadj=no])])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; tm.tm_gmtoff;]])],
	    [tcl_cv_member_tm_gmtoff=yes],
	    [tcl_cv_member_tm_gmtoff=no])])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]],
	    [[extern long timezone;
	    timezone += 1;
	    exit (0);]])],
	    [tcl_cv_timezone_long=yes],[tcl_cv_timezone_long=no])])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]],
		[[extern time_t timezone;
		timezone += 1;
		exit (0);]])],
		[tcl_cv_timezone_time=yes],[tcl_cv_timezone_time=no])])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

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







|
|
<





|
|
<









|
|

|
|







|
|

|
|







2523
2524
2525
2526
2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2537
2538

2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
AC_DEFUN([SC_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME

    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])

    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])

    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_TRY_COMPILE([#include <time.h>],
	    [extern long timezone;
	    timezone += 1;
	    exit (0);],
	    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_TRY_COMPILE([#include <time.h>],
		[extern time_t timezone;
		timezone += 1;
		exit (0);],
		tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

#--------------------------------------------------------------------
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
#
#--------------------------------------------------------------------

AC_DEFUN([SC_BUGGY_STRTOD], [
    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
    if test "$tcl_strtod" = 1; then
	AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
	    AC_RUN_IFELSE([AC_LANG_SOURCE([[
		#include <stdlib.h>
		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(nanString, &term);
		    if ((term != nanString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(spaceString, &term);
		    if (term == (spaceString+1)) {
			exit(1);
		    }
		    exit(0);
		}]])],
		[tcl_cv_strtod_buggy=ok],
		[tcl_cv_strtod_buggy=buggy],
		[tcl_cv_strtod_buggy=buggy])])
	if test "$tcl_cv_strtod_buggy" = buggy; then
	    AC_LIBOBJ([fixstrtod])
	    USE_COMPAT=1
	    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
	fi
    fi
])







|
<


















<
|
|
<







2588
2589
2590
2591
2592
2593
2594
2595

2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613

2614
2615

2616
2617
2618
2619
2620
2621
2622
#
#--------------------------------------------------------------------

AC_DEFUN([SC_BUGGY_STRTOD], [
    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
    if test "$tcl_strtod" = 1; then
	AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
	    AC_TRY_RUN([

		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(nanString, &term);
		    if ((term != nanString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(spaceString, &term);
		    if (term == (spaceString+1)) {
			exit(1);
		    }
		    exit(0);

		}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
		    tcl_cv_strtod_buggy=buggy)])

	if test "$tcl_cv_strtod_buggy" = buggy; then
	    AC_LIBOBJ([fixstrtod])
	    USE_COMPAT=1
	    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
	fi
    fi
])
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])],[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define $1 1
$2]], [[$3]])],
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)]))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([SC_TCL_EARLY_FLAGS],[







|
|
|

|







2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    AC_TRY_COMPILE([[#define ]$1[ 1
]$2], $3,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([SC_TCL_EARLY_FLAGS],[
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])],
	    [tcl_type_64bit=__int64],[tcl_type_64bit="long long"])
	# See if we should use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) {
            case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
        }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]],
		[[struct dirent64 p;]])],[tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);]])],
		[tcl_cv_DIR64=yes],[tcl_cv_DIR64=no])])
	if test "x${tcl_cv_DIR64}" = "xyes" ; then
	    AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/stat.h>]], [[struct stat64 p;
]])],
		[tcl_cv_struct_stat64=yes],[tcl_cv_struct_stat64=no])])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[off64_t offset;
]])],
		[tcl_cv_type_off64_t=yes],[tcl_cv_type_off64_t=no])])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])







|
|



|
|
|










|
|
|





|
|
|
|





|
|
|







|
|
|







2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we should use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 p;],
		tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);],
		tcl_cv_DIR64=yes,tcl_cv_DIR64=no)])
	if test "x${tcl_cv_DIR64}" = "xyes" ; then
	    AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
],
		tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
],
		tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AS_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: iso8859-1)]),
	[with_tcencoding=${withval}])

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
	    [What encoding should be used for embedded configuration info?])
    else
	AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
	    [What encoding should be used for embedded configuration info?])







|

|







2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AC_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: iso8859-1)]),
	with_tcencoding=${withval})

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
	    [What encoding should be used for embedded configuration info?])
    else
	AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
	    [What encoding should be used for embedded configuration info?])
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
    AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
    if test ["$tcl_ok"] = 1; then
	AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
	    AC_RUN_IFELSE([AC_LANG_SOURCE([[[
#include <stdlib.h>
#include <string.h>
int main() {]$2[}]]])],[tcl_cv_$1_unbroken=ok],[tcl_cv_$1_unbroken=broken],[tcl_cv_$1_unbroken=unknown]))

	if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
    if test ["$tcl_ok"] = 0; then







<
<
<
|
>







2875
2876
2877
2878
2879
2880
2881



2882
2883
2884
2885
2886
2887
2888
2889
2890
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
    AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
    if test ["$tcl_ok"] = 1; then
	AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],



	    AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
		[tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
	if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
    if test ["$tcl_ok"] = 0; then
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
#	Might define the following vars:
#		HAVE_GETHOSTBYADDR_R
#		HAVE_GETHOSTBYADDR_R_7
#		HAVE_GETHOSTBYADDR_R_8
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [
    # Avoids picking hidden internal symbol from libc
    SC_TCL_GETHOSTBYADDR_R_DECL

    if test "$tcl_cv_api_gethostbyaddr_r" = yes; then
	SC_TCL_GETHOSTBYADDR_R_TYPE
    fi
])

AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [
    tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include <netdb.h>])
])

AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [
    AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <netdb.h>
    ]], [[
	char *addr;
	int length;
	int type;
	struct hostent *result;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
			       &h_errnop);
    ]])],[tcl_cv_api_gethostbyaddr_r_7=yes],[tcl_cv_api_gethostbyaddr_r_7=no])])
    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,
	    [Define to 1 if gethostbyaddr_r takes 7 args.])
    else
	AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <netdb.h>
	]], [[
	    char *addr;
	    int length;
	    int type;
	    struct hostent *result, *resultp;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
				   &resultp, &h_errnop);
	]])],[tcl_cv_api_gethostbyaddr_r_8=yes],[tcl_cv_api_gethostbyaddr_r_8=no])])
	tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,
		[Define to 1 if gethostbyaddr_r takes 8 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then







|
<
<
<
<
<
<
<
<
<
<
<
<
<

|

|










|






|

|










|







2906
2907
2908
2909
2910
2911
2912
2913













2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
#	Might define the following vars:
#		HAVE_GETHOSTBYADDR_R
#		HAVE_GETHOSTBYADDR_R_7
#		HAVE_GETHOSTBYADDR_R_8
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [AC_CHECK_FUNC(gethostbyaddr_r, [













    AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
    AC_TRY_COMPILE([
	#include <netdb.h>
    ], [
	char *addr;
	int length;
	int type;
	struct hostent *result;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
			       &h_errnop);
    ], tcl_cv_api_gethostbyaddr_r_7=yes, tcl_cv_api_gethostbyaddr_r_7=no)])
    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,
	    [Define to 1 if gethostbyaddr_r takes 7 args.])
    else
	AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [
	AC_TRY_COMPILE([
	    #include <netdb.h>
	], [
	    char *addr;
	    int length;
	    int type;
	    struct hostent *result, *resultp;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
				   &resultp, &h_errnop);
	], tcl_cv_api_gethostbyaddr_r_8=yes, tcl_cv_api_gethostbyaddr_r_8=no)])
	tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,
		[Define to 1 if gethostbyaddr_r takes 8 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		HAVE_GETHOSTBYNAME_R
#		HAVE_GETHOSTBYNAME_R_3
#		HAVE_GETHOSTBYNAME_R_5
#		HAVE_GETHOSTBYNAME_R_6
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [
    # Avoids picking hidden internal symbol from libc
    SC_TCL_GETHOSTBYNAME_R_DECL

    if test "$tcl_cv_api_gethostbyname_r" = yes; then
	SC_TCL_GETHOSTBYNAME_R_TYPE
    fi
])

AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [
    tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include <netdb.h>])
])

AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [
    AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <netdb.h>
    ]], [[
	char *name;
	struct hostent *he, *res;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
    ]])],[tcl_cv_api_gethostbyname_r_6=yes],[tcl_cv_api_gethostbyname_r_6=no])])
    tcl_ok=$tcl_cv_api_gethostbyname_r_6
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,
	    [Define to 1 if gethostbyname_r takes 6 args.])
    else
	AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <netdb.h>
	]], [[
	    char *name;
	    struct hostent *he;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
	]])],[tcl_cv_api_gethostbyname_r_5=yes],[tcl_cv_api_gethostbyname_r_5=no])])
	tcl_ok=$tcl_cv_api_gethostbyname_r_5
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,
		[Define to 1 if gethostbyname_r takes 5 args.])
	else
	    AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#include <netdb.h>
	    ]], [[
		char *name;
		struct hostent *he;
		struct hostent_data data;

		(void) gethostbyname_r(name, he, &data);
	    ]])],[tcl_cv_api_gethostbyname_r_3=yes],[tcl_cv_api_gethostbyname_r_3=no])])
	    tcl_ok=$tcl_cv_api_gethostbyname_r_3
	    if test "$tcl_ok" = yes; then
		AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,
		    [Define to 1 if gethostbyname_r takes 3 args.])
	    fi
	fi
    fi







|
|
|
|



|
<
<
<
<
<
<
<
<
<
<
<
<
<

|

|







|






|

|







|






|

|





|







2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981













2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		HAVE_GETHOSTBYADDR_R
#		HAVE_GETHOSTBYADDR_R_3
#		HAVE_GETHOSTBYADDR_R_5
#		HAVE_GETHOSTBYADDR_R_6
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [AC_CHECK_FUNC(gethostbyname_r, [













    AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
    AC_TRY_COMPILE([
	#include <netdb.h>
    ], [
	char *name;
	struct hostent *he, *res;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
    ], tcl_cv_api_gethostbyname_r_6=yes, tcl_cv_api_gethostbyname_r_6=no)])
    tcl_ok=$tcl_cv_api_gethostbyname_r_6
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,
	    [Define to 1 if gethostbyname_r takes 6 args.])
    else
	AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [
	AC_TRY_COMPILE([
	    #include <netdb.h>
	], [
	    char *name;
	    struct hostent *he;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
	], tcl_cv_api_gethostbyname_r_5=yes, tcl_cv_api_gethostbyname_r_5=no)])
	tcl_ok=$tcl_cv_api_gethostbyname_r_5
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,
		[Define to 1 if gethostbyname_r takes 5 args.])
	else
	    AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [
	    AC_TRY_COMPILE([
		#include <netdb.h>
	    ], [
		char *name;
		struct hostent *he;
		struct hostent_data data;

		(void) gethostbyname_r(name, he, &data);
	    ], tcl_cv_api_gethostbyname_r_3=yes, tcl_cv_api_gethostbyname_r_3=no)])
	    tcl_ok=$tcl_cv_api_gethostbyname_r_3
	    if test "$tcl_ok" = yes; then
		AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,
		    [Define to 1 if gethostbyname_r takes 3 args.])
	    fi
	fi
    fi
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
#	Might define the following vars:
#		HAVE_GETADDRINFO
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETADDRINFO], [AC_CHECK_FUNC(getaddrinfo, [
    AC_CACHE_CHECK([for working getaddrinfo], tcl_cv_api_getaddrinfo, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <netdb.h>
    ]], [[
	const char *name, *port;
	struct addrinfo *aiPtr, hints;
	(void)getaddrinfo(name,port, &hints, &aiPtr);
	(void)freeaddrinfo(aiPtr);
    ]])],[tcl_cv_api_getaddrinfo=yes],[tcl_cv_getaddrinfo=no])])
    tcl_ok=$tcl_cv_api_getaddrinfo
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETADDRINFO, 1,
	    [Define to 1 if getaddrinfo is available.])
    fi
])])








|

|




|







3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
#	Might define the following vars:
#		HAVE_GETADDRINFO
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETADDRINFO], [AC_CHECK_FUNC(getaddrinfo, [
    AC_CACHE_CHECK([for working getaddrinfo], tcl_cv_api_getaddrinfo, [
    AC_TRY_COMPILE([
	#include <netdb.h>
    ], [
	const char *name, *port;
	struct addrinfo *aiPtr, hints;
	(void)getaddrinfo(name,port, &hints, &aiPtr);
	(void)freeaddrinfo(aiPtr);
    ], tcl_cv_api_getaddrinfo=yes, tcl_cv_getaddrinfo=no)])
    tcl_ok=$tcl_cv_api_getaddrinfo
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETADDRINFO, 1,
	    [Define to 1 if getaddrinfo is available.])
    fi
])])

3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
#		HAVE_GETPWUID_R_4
#		HAVE_GETPWUID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [
    AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <pwd.h>
    ]], [[
	uid_t uid;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
    ]])],[tcl_cv_api_getpwuid_r_5=yes],[tcl_cv_api_getpwuid_r_5=no])])
    tcl_ok=$tcl_cv_api_getpwuid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWUID_R_5, 1,
	    [Define to 1 if getpwuid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <pwd.h>
	]], [[
	    uid_t uid;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(uid, &pw, buf, buflen);
	]])],[tcl_cv_api_getpwuid_r_4=yes],[tcl_cv_api_getpwuid_r_4=no])])
	tcl_ok=$tcl_cv_api_getpwuid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWUID_R_4, 1,
		[Define to 1 if getpwuid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then







|


|






|






|


|






|







3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
#		HAVE_GETPWUID_R_4
#		HAVE_GETPWUID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [
    AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [
    AC_TRY_COMPILE([
	#include <sys/types.h>
	#include <pwd.h>
    ], [
	uid_t uid;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
    ], tcl_cv_api_getpwuid_r_5=yes, tcl_cv_api_getpwuid_r_5=no)])
    tcl_ok=$tcl_cv_api_getpwuid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWUID_R_5, 1,
	    [Define to 1 if getpwuid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [
	AC_TRY_COMPILE([
	    #include <sys/types.h>
	    #include <pwd.h>
	], [
	    uid_t uid;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(uid, &pw, buf, buflen);
	], tcl_cv_api_getpwuid_r_4=yes, tcl_cv_api_getpwuid_r_4=no)])
	tcl_ok=$tcl_cv_api_getpwuid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWUID_R_4, 1,
		[Define to 1 if getpwuid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
#		HAVE_GETPWNAM_R_4
#		HAVE_GETPWNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [
    AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <pwd.h>
    ]], [[
	char *name;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwnam_r(name, &pw, buf, buflen, &pwp);
    ]])],[tcl_cv_api_getpwnam_r_5=yes],[tcl_cv_api_getpwnam_r_5=no])])
    tcl_ok=$tcl_cv_api_getpwnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWNAM_R_5, 1,
	    [Define to 1 if getpwnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <pwd.h>
	]], [[
	    char *name;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(name, &pw, buf, buflen);
	]])],[tcl_cv_api_getpwnam_r_4=yes],[tcl_cv_api_getpwnam_r_4=no])])
	tcl_ok=$tcl_cv_api_getpwnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWNAM_R_4, 1,
		[Define to 1 if getpwnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then







|


|






|






|


|






|







3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
#		HAVE_GETPWNAM_R_4
#		HAVE_GETPWNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [
    AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [
    AC_TRY_COMPILE([
	#include <sys/types.h>
	#include <pwd.h>
    ], [
	char *name;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwnam_r(name, &pw, buf, buflen, &pwp);
    ], tcl_cv_api_getpwnam_r_5=yes, tcl_cv_api_getpwnam_r_5=no)])
    tcl_ok=$tcl_cv_api_getpwnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWNAM_R_5, 1,
	    [Define to 1 if getpwnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [
	AC_TRY_COMPILE([
	    #include <sys/types.h>
	    #include <pwd.h>
	], [
	    char *name;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(name, &pw, buf, buflen);
	], tcl_cv_api_getpwnam_r_4=yes, tcl_cv_api_getpwnam_r_4=no)])
	tcl_ok=$tcl_cv_api_getpwnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWNAM_R_4, 1,
		[Define to 1 if getpwnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
#		HAVE_GETGRGID_R_4
#		HAVE_GETGRGID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [
    AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <grp.h>
    ]], [[
	gid_t gid;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrgid_r(gid, &gr, buf, buflen, &grp);
    ]])],[tcl_cv_api_getgrgid_r_5=yes],[tcl_cv_api_getgrgid_r_5=no])])
    tcl_ok=$tcl_cv_api_getgrgid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRGID_R_5, 1,
	    [Define to 1 if getgrgid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <grp.h>
	]], [[
	    gid_t gid;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrgid_r(gid, &gr, buf, buflen);
	]])],[tcl_cv_api_getgrgid_r_4=yes],[tcl_cv_api_getgrgid_r_4=no])])
	tcl_ok=$tcl_cv_api_getgrgid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRGID_R_4, 1,
		[Define to 1 if getgrgid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then







|


|






|






|


|






|







3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
#		HAVE_GETGRGID_R_4
#		HAVE_GETGRGID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [
    AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [
    AC_TRY_COMPILE([
	#include <sys/types.h>
	#include <grp.h>
    ], [
	gid_t gid;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrgid_r(gid, &gr, buf, buflen, &grp);
    ], tcl_cv_api_getgrgid_r_5=yes, tcl_cv_api_getgrgid_r_5=no)])
    tcl_ok=$tcl_cv_api_getgrgid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRGID_R_5, 1,
	    [Define to 1 if getgrgid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [
	AC_TRY_COMPILE([
	    #include <sys/types.h>
	    #include <grp.h>
	], [
	    gid_t gid;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrgid_r(gid, &gr, buf, buflen);
	], tcl_cv_api_getgrgid_r_4=yes, tcl_cv_api_getgrgid_r_4=no)])
	tcl_ok=$tcl_cv_api_getgrgid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRGID_R_4, 1,
		[Define to 1 if getgrgid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
#		HAVE_GETGRNAM_R_4
#		HAVE_GETGRNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
    AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <grp.h>
    ]], [[
	char *name;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrnam_r(name, &gr, buf, buflen, &grp);
    ]])],[tcl_cv_api_getgrnam_r_5=yes],[tcl_cv_api_getgrnam_r_5=no])])
    tcl_ok=$tcl_cv_api_getgrnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRNAM_R_5, 1,
	    [Define to 1 if getgrnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <grp.h>
	]], [[
	    char *name;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrnam_r(name, &gr, buf, buflen);
	]])],[tcl_cv_api_getgrnam_r_4=yes],[tcl_cv_api_getgrnam_r_4=no])])
	tcl_ok=$tcl_cv_api_getgrnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRNAM_R_4, 1,
		[Define to 1 if getgrnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then







|


|






|






|


|






|







3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
#		HAVE_GETGRNAM_R_4
#		HAVE_GETGRNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
    AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [
    AC_TRY_COMPILE([
	#include <sys/types.h>
	#include <grp.h>
    ], [
	char *name;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrnam_r(name, &gr, buf, buflen, &grp);
    ], tcl_cv_api_getgrnam_r_5=yes, tcl_cv_api_getgrnam_r_5=no)])
    tcl_ok=$tcl_cv_api_getgrnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRNAM_R_5, 1,
	    [Define to 1 if getgrnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [
	AC_TRY_COMPILE([
	    #include <sys/types.h>
	    #include <grp.h>
	], [
	    char *name;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrnam_r(name, &gr, buf, buflen);
	], tcl_cv_api_getgrnam_r_4=yes, tcl_cv_api_getgrnam_r_4=no)])
	tcl_ok=$tcl_cv_api_getgrnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRNAM_R_4, 1,
		[Define to 1 if getgrnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then

Changes to unix/tclConfig.h.in.

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

/* Do we have access to Darwin CoreFoundation.framework? */
#undef HAVE_COREFOUNDATION

/* Is the cpuid instruction usable? */
#undef HAVE_CPUID

/* Define to 1 if you have the declaration of `gethostbyaddr_r', and to 0 if
   you don't. */
#undef HAVE_DECL_GETHOSTBYADDR_R

/* Define to 1 if you have the declaration of `gethostbyname_r', and to 0 if
   you don't. */
#undef HAVE_DECL_GETHOSTBYNAME_R

/* Is 'DIR64' in <sys/types.h>? */
#undef HAVE_DIR64

/* Do we have fts functions? */
#undef HAVE_FTS

/* Define to 1 if getaddrinfo is available. */
#undef HAVE_GETADDRINFO

/* Define to 1 if you have the `getattrlist' function. */







<
<
<
<
<
<
<
<
<
<
<







33
34
35
36
37
38
39











40
41
42
43
44
45
46

/* Do we have access to Darwin CoreFoundation.framework? */
#undef HAVE_COREFOUNDATION

/* Is the cpuid instruction usable? */
#undef HAVE_CPUID












/* Do we have fts functions? */
#undef HAVE_FTS

/* Define to 1 if getaddrinfo is available. */
#undef HAVE_GETADDRINFO

/* Define to 1 if you have the `getattrlist' function. */
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

/* Define to 1 if getpwuid_r takes 5 args. */
#undef HAVE_GETPWUID_R_5

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Define to 1 if the system has the type `intptr_t'. */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Do we have nl_langinfo()? */
#undef HAVE_LANGINFO







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

/* Define to 1 if getpwuid_r takes 5 args. */
#undef HAVE_GETPWUID_R_5

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Do we have the intptr_t type? */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Do we have nl_langinfo()? */
#undef HAVE_LANGINFO
199
200
201
202
203
204
205



206
207
208
209
210
211
212
#undef HAVE_STRING_H

/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL

/* Is 'struct dirent64' in <sys/types.h>? */
#undef HAVE_STRUCT_DIRENT64




/* Is 'struct stat64' in <sys/stat.h>? */
#undef HAVE_STRUCT_STAT64

/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE








>
>
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#undef HAVE_STRING_H

/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL

/* Is 'struct dirent64' in <sys/types.h>? */
#undef HAVE_STRUCT_DIRENT64

/* Is 'DIR64' in <sys/types.h>? */
#undef HAVE_DIR64

/* Is 'struct stat64' in <sys/stat.h>? */
#undef HAVE_STRUCT_STAT64

/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

/* Should we use the tm_tzadj field of struct tm? */
#undef HAVE_TM_TZADJ

/* Is off64_t in <sys/types.h>? */
#undef HAVE_TYPE_OFF64_T

/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

/* Should we use the tm_tzadj field of struct tm? */
#undef HAVE_TM_TZADJ

/* Is off64_t in <sys/types.h>? */
#undef HAVE_TYPE_OFF64_T

/* Do we have the uintptr_t type? */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
481
482
483
484
485
486
487



488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506



507
508
509
510
511
512
513
514
#undef gid_t

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif




/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t

/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t

/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t

/* Define as int if socklen_t is not available */
#undef socklen_t

/* Do we want to use the strtod() in compat? */
#undef strtod

/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t





    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_VERSION
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */







>
>
>



















>
>
>




|
|
<

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510

511
#undef gid_t

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif

/* Signed integer type wide enough to hold a pointer. */
#undef intptr_t

/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t

/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t

/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t

/* Define as int if socklen_t is not available */
#undef socklen_t

/* Do we want to use the strtod() in compat? */
#undef strtod

/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t

/* Unsigned integer type wide enough to hold a pointer. */
#undef uintptr_t


    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME

    #endif /* _TCLCONFIG */

Changes to unix/tclLoadDyld.c.

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

    if (codeSize >= 0) {
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
	const struct fat_header *fh = buffer;
	uint32_t ms = 0;
#ifndef __LP64__
	const struct mach_header *mh = NULL;
#	define mh_size  sizeof(struct mach_header)
#	define mh_magic MH_MAGIC
#	define arch_abi 0
#else
	const struct mach_header_64 *mh = NULL;
#	define mh_size  sizeof(struct mach_header_64)
#	define mh_magic MH_MAGIC_64
#	define arch_abi CPU_ARCH_ABI64
#endif

	if ((size_t) codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*







|
|
|


|
|
|







629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

    if (codeSize >= 0) {
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
	const struct fat_header *fh = buffer;
	uint32_t ms = 0;
#ifndef __LP64__
	const struct mach_header *mh = NULL;
	#define mh_size  sizeof(struct mach_header)
	#define mh_magic MH_MAGIC
	#define arch_abi 0
#else
	const struct mach_header_64 *mh = NULL;
	#define mh_size  sizeof(struct mach_header_64)
	#define mh_magic MH_MAGIC_64
	#define arch_abi CPU_ARCH_ABI64
#endif

	if ((size_t) codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*

Changes to unix/tclUnixChan.c.

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
				 * Must be the first field. */
    IOSTATE savedState;		/* Initial state of device. Used to reset
				 * state when device closed. */
} TtyState;

/*
 * The following structure is used to set or get the serial port attributes in
 * a platform-independent manner.
 */

typedef struct TtyAttrs {
    int baud;
    int parity;
    int data;
    int stop;







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
				 * Must be the first field. */
    IOSTATE savedState;		/* Initial state of device. Used to reset
				 * state when device closed. */
} TtyState;

/*
 * The following structure is used to set or get the serial port attributes in
 * a platform-independant manner.
 */

typedef struct TtyAttrs {
    int baud;
    int parity;
    int data;
    int stop;
340
341
342
343
344
345
346

347
348
349
350
351
352
353
 *
 * Side effects:
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */


static int
FileBlockModeProc(
    ClientData instanceData,	/* File state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{







>







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
 *
 * Side effects:
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
FileBlockModeProc(
    ClientData instanceData,	/* File state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
 *
 * Side effects:
 *	Sets the device into blocking or nonblocking mode.
 *
 *----------------------------------------------------------------------
 */


static int
TcpBlockModeProc(
    ClientData instanceData,	/* Socket state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{







>







1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
 *
 * Side effects:
 *	Sets the device into blocking or nonblocking mode.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TcpBlockModeProc(
    ClientData instanceData,	/* Socket state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
 *
 * Side effects:
 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */


static int
TcpInputProc(
    ClientData instanceData,	/* Socket state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCodePtr)		/* Where to store error code. */







>







1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
 *
 * Side effects:
 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TcpInputProc(
    ClientData instanceData,	/* Socket state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCodePtr)		/* Where to store error code. */
2026
2027
2028
2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039
 *
 * Side effects:
 *	Closes the socket of the channel.
 *
 *----------------------------------------------------------------------
 */


static int
TcpCloseProc(
    ClientData instanceData,	/* The socket to close. */
    Tcl_Interp *interp)		/* For error reporting - unused. */
{
    TcpState *statePtr = (TcpState *) instanceData;
    int errorCode = 0;







>







2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
 *
 * Side effects:
 *	Closes the socket of the channel.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TcpCloseProc(
    ClientData instanceData,	/* The socket to close. */
    Tcl_Interp *interp)		/* For error reporting - unused. */
{
    TcpState *statePtr = (TcpState *) instanceData;
    int errorCode = 0;
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
TcpGetHandleProc(
    ClientData instanceData,	/* The socket state. */
    int direction,		/* Not used. */
    ClientData *handlePtr)	/* Where to store the handle. */
{
    TcpState *statePtr = (TcpState *) instanceData;







>







2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TcpGetHandleProc(
    ClientData instanceData,	/* The socket state. */
    int direction,		/* Not used. */
    ClientData *handlePtr)	/* Where to store the handle. */
{
    TcpState *statePtr = (TcpState *) instanceData;
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
    int status, sock, asyncConnect, curState;
    struct sockaddr_in sockaddr;	/* socket address */
    struct sockaddr_in mysockaddr;	/* Socket address for client */
    TcpState *statePtr;
    const char *errorMsg = NULL;

    sock = -1;
    if (!CreateSocketAddress(&sockaddr, host, port, server, &errorMsg)) {
	goto addressError;
    }
    if ((myaddr != NULL || myport != 0) &&
	    !CreateSocketAddress(&mysockaddr, myaddr, myport, 1, &errorMsg)) {
	goto addressError;
    }








|







2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
    int status, sock, asyncConnect, curState;
    struct sockaddr_in sockaddr;	/* socket address */
    struct sockaddr_in mysockaddr;	/* Socket address for client */
    TcpState *statePtr;
    const char *errorMsg = NULL;

    sock = -1;
    if (!CreateSocketAddress(&sockaddr, host, port, 0, &errorMsg)) {
	goto addressError;
    }
    if ((myaddr != NULL || myport != 0) &&
	    !CreateSocketAddress(&mysockaddr, myaddr, myport, 1, &errorMsg)) {
	goto addressError;
    }

2844
2845
2846
2847
2848
2849
2850

2851
2852
2853
2854
2855
2856
2857
 * Side effects:
 *	Creates a new connection socket. Calls the registered callback for the
 *	connection acceptance mechanism.
 *
 *----------------------------------------------------------------------
 */


static void
TcpAccept(
    ClientData data,		/* Callback token. */
    int mask)			/* Not used. */
{
    TcpState *sockState;	/* Client data of server socket. */
    int newsock;		/* The new client socket */







>







2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
 * Side effects:
 *	Creates a new connection socket. Calls the registered callback for the
 *	connection acceptance mechanism.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static void
TcpAccept(
    ClientData data,		/* Callback token. */
    int mask)			/* Not used. */
{
    TcpState *sockState;	/* Client data of server socket. */
    int newsock;		/* The new client socket */

Changes to unix/tclUnixFCmd.c.

1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

    while ((ent = fts_read(fts)) != NULL) {
	unsigned short info = ent->fts_info;
	char *path = ent->fts_path + sourceLen;
	unsigned short pathlen = ent->fts_pathlen - sourceLen;
	int type;
	Tcl_StatBuf *statBufPtr = NULL;

	if (info == FTS_DNR || info == FTS_ERR || info == FTS_NS) {
	    errfile = ent->fts_path;
	    break;
	}
	Tcl_DStringAppend(sourcePtr, path, pathlen);
	if (targetPtr != NULL) {
	    Tcl_DStringAppend(targetPtr, path, pathlen);







|







1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

    while ((ent = fts_read(fts)) != NULL) {
	unsigned short info = ent->fts_info;
	char *path = ent->fts_path + sourceLen;
	unsigned short pathlen = ent->fts_pathlen - sourceLen;
	int type;
	Tcl_StatBuf *statBufPtr = NULL;
	
	if (info == FTS_DNR || info == FTS_ERR || info == FTS_NS) {
	    errfile = ent->fts_path;
	    break;
	}
	Tcl_DStringAppend(sourcePtr, path, pathlen);
	if (targetPtr != NULL) {
	    Tcl_DStringAppend(targetPtr, path, pathlen);

Changes to unix/tclUnixFile.c.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
TclpFindExecutable(
    CONST char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_Encoding encoding;
#ifdef __CYGWIN__
    int length;
    wchar_t buf[PATH_MAX] = L"";
    char name[PATH_MAX * 3 + 1];
    (void)argv0;

    GetModuleFileNameW(NULL, (void *)buf, sizeof(buf)/sizeof(wchar_t));
    cygwin_conv_path(3, buf, name, sizeof(name));
    length = strlen(name);
    if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
	/* Strip '.exe' part. */
	length -= 4;
    }
    encoding = Tcl_GetEncoding(NULL, NULL);
    TclSetObjNameOfExecutable(







|
|
<
<
|
|







38
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55
TclpFindExecutable(
    CONST char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_Encoding encoding;
#ifdef __CYGWIN__
    int length;
    char buf[PATH_MAX * 2];
    char name[PATH_MAX * TCL_UTF_MAX + 1];


    GetModuleFileNameW(NULL, buf, PATH_MAX);
    cygwin_conv_path(3, buf, name, PATH_MAX);
    length = strlen(name);
    if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
	/* Strip '.exe' part. */
	length -= 4;
    }
    encoding = Tcl_GetEncoding(NULL, NULL);
    TclSetObjNameOfExecutable(
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

    /*
     * Search through all the directories named in the PATH variable to see if
     * argv[0] is in one of them. If so, use that file name.
     */

    while (1) {
	while (TclIsSpaceProcM(*p)) {
	    p++;
	}
	name = p;
	while ((*p != ':') && (*p != 0)) {
	    p++;
	}
	Tcl_DStringSetLength(&buffer, 0);







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

    /*
     * Search through all the directories named in the PATH variable to see if
     * argv[0] is in one of them. If so, use that file name.
     */

    while (1) {
	while (TclIsSpaceProc(*p)) {
	    p++;
	}
	name = p;
	while ((*p != ':') && (*p != 0)) {
	    p++;
	}
	Tcl_DStringSetLength(&buffer, 0);
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

	/*
	 * Check to see if -type or the pattern requests hidden files.
	 */

	matchHiddenPat = (pattern[0] == '.')
		|| ((pattern[0] == '\\') && (pattern[1] == '.'));
	matchHidden = matchHiddenPat
		|| (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
	while ((entryPtr = TclOSreaddir(d)) != NULL) {	/* INTL: Native. */
	    Tcl_DString utfDs;
	    CONST char *utfname;

	    /*
	     * Skip this file if it doesn't agree with the hidden parameters







|







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

	/*
	 * Check to see if -type or the pattern requests hidden files.
	 */

	matchHiddenPat = (pattern[0] == '.')
		|| ((pattern[0] == '\\') && (pattern[1] == '.'));
	matchHidden = matchHiddenPat 
		|| (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
	while ((entryPtr = TclOSreaddir(d)) != NULL) {	/* INTL: Native. */
	    Tcl_DString utfDs;
	    CONST char *utfname;

	    /*
	     * Skip this file if it doesn't agree with the hidden parameters
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203












1204




1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
 */

int
TclpUtime(
    Tcl_Obj *pathPtr,		/* File to modify */
    struct utimbuf *tval)	/* New modification date structure */
{
    return utime((const char *)Tcl_FSGetNativePath(pathPtr), tval);
}
#ifdef __CYGWIN__
int
TclOSstat(
    const char *name,
    void *cygstat)
{
    struct stat buf;
    Tcl_StatBuf *statBuf = (Tcl_StatBuf *)cygstat;
    int result = stat(name, &buf);

















    statBuf->st_mode = buf.st_mode;
    statBuf->st_ino = buf.st_ino;
    statBuf->st_dev = buf.st_dev;
    statBuf->st_rdev = buf.st_rdev;
    statBuf->st_nlink = buf.st_nlink;
    statBuf->st_uid = buf.st_uid;
    statBuf->st_gid = buf.st_gid;
    statBuf->st_size = buf.st_size;
    statBuf->st_atime = buf.st_atime;
    statBuf->st_mtime = buf.st_mtime;
    statBuf->st_ctime = buf.st_ctime;
    return result;
}

int
TclOSlstat(
    const char *name,
    void *cygstat)
{
    struct stat buf;
    Tcl_StatBuf *statBuf = (Tcl_StatBuf *)cygstat;
    int result = lstat(name, &buf);

    statBuf->st_mode = buf.st_mode;
    statBuf->st_ino = buf.st_ino;
    statBuf->st_dev = buf.st_dev;
    statBuf->st_rdev = buf.st_rdev;
    statBuf->st_nlink = buf.st_nlink;
    statBuf->st_uid = buf.st_uid;
    statBuf->st_gid = buf.st_gid;
    statBuf->st_size = buf.st_size;
    statBuf->st_atime = buf.st_atime;
    statBuf->st_mtime = buf.st_mtime;
    statBuf->st_ctime = buf.st_ctime;
    return result;
}
#endif /* CYGWIN */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|


<
<
|
<
<

|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|








1184
1185
1186
1187
1188
1189
1190
1191
1192
1193


1194


1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227























1228
1229
1230
1231
1232
1233
1234
1235
1236
 */

int
TclpUtime(
    Tcl_Obj *pathPtr,		/* File to modify */
    struct utimbuf *tval)	/* New modification date structure */
{
    return utime(Tcl_FSGetNativePath(pathPtr), tval);
}
#ifdef __CYGWIN__


int TclOSstat(const char *name, void *cygstat) {


    struct stat buf;
    Tcl_StatBuf *statBuf = cygstat;
    int result = stat(name, &buf);
    statBuf->st_mode = buf.st_mode;
    statBuf->st_ino = buf.st_ino;
    statBuf->st_dev = buf.st_dev;
    statBuf->st_rdev = buf.st_rdev;
    statBuf->st_nlink = buf.st_nlink;
    statBuf->st_uid = buf.st_uid;
    statBuf->st_gid = buf.st_gid;
    statBuf->st_size = buf.st_size;
    statBuf->st_atime = buf.st_atime;
    statBuf->st_mtime = buf.st_mtime;
    statBuf->st_ctime = buf.st_ctime;
    return result;
}
int TclOSlstat(const char *name, void *cygstat) {
    struct stat buf;
    Tcl_StatBuf *statBuf = cygstat;
    int result = lstat(name, &buf);
    statBuf->st_mode = buf.st_mode;
    statBuf->st_ino = buf.st_ino;
    statBuf->st_dev = buf.st_dev;
    statBuf->st_rdev = buf.st_rdev;
    statBuf->st_nlink = buf.st_nlink;
    statBuf->st_uid = buf.st_uid;
    statBuf->st_gid = buf.st_gid;
    statBuf->st_size = buf.st_size;
    statBuf->st_atime = buf.st_atime;
    statBuf->st_mtime = buf.st_mtime;
    statBuf->st_ctime = buf.st_ctime;
    return result;
}























#endif

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclUnixInit.c.

35
36
37
38
39
40
41





42
43
44
45
46
47
48
49
50
51
52
#ifdef __CYGWIN__
DLLIMPORT extern __stdcall unsigned char GetVersionExW(void *);
DLLIMPORT extern __stdcall void *GetModuleHandleW(const void *);
DLLIMPORT extern __stdcall void FreeLibrary(void *);
DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *);
DLLIMPORT extern __stdcall void GetSystemInfo(void *);






#define NUMPROCESSORS 15
static const char *const processors[NUMPROCESSORS] = {
    "i686", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "x86_64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};

typedef struct {
  union {
    DWORD  dwOemId;
    struct {
      int wProcessorArchitecture;







>
>
>
>
>
|

|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifdef __CYGWIN__
DLLIMPORT extern __stdcall unsigned char GetVersionExW(void *);
DLLIMPORT extern __stdcall void *GetModuleHandleW(const void *);
DLLIMPORT extern __stdcall void FreeLibrary(void *);
DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *);
DLLIMPORT extern __stdcall void GetSystemInfo(void *);

#define NUMPLATFORMS 4
static const char *const platforms[NUMPLATFORMS] = {
    "Win32s", "Windows 95", "Windows NT", "Windows CE"
};

#define NUMPROCESSORS 11
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
};

typedef struct {
  union {
    DWORD  dwOemId;
    struct {
      int wProcessorArchitecture;
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406


/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependent things like signals and
 *	floating-point error handling.
 *
 *	Called at process initialization time.
 *
 * Results:
 *	None.
 *







|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411


/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependant things like signals and
 *	floating-point error handling.
 *
 *	Called at process initialization time.
 *
 * Results:
 *	None.
 *
932
933
934
935
936
937
938

939


940
941
942
943
944
945
946
	    GetVersionExW(&osInfo);
	}
	osInfoInitialized = 1;
    }

    GetSystemInfo(&sysInfo);


    Tcl_SetVar2(interp, "tcl_platform", "os", "Windows NT", TCL_GLOBAL_ONLY);


    sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
    if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) {
	Tcl_SetVar2(interp, "tcl_platform", "machine",
		processors[sysInfo.wProcessorArchitecture],
		TCL_GLOBAL_ONLY);
    }







>
|
>
>







937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
	    GetVersionExW(&osInfo);
	}
	osInfoInitialized = 1;
    }

    GetSystemInfo(&sysInfo);

    if (osInfo.dwPlatformId < NUMPLATFORMS) {
	Tcl_SetVar2(interp, "tcl_platform", "os",
		platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY);
    }
    sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
    if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) {
	Tcl_SetVar2(interp, "tcl_platform", "machine",
		processors[sysInfo.wProcessorArchitecture],
		TCL_GLOBAL_ONLY);
    }

Changes to unix/tclUnixNotfy.c.

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

static int triggerPipe = -1;

/*
 * The notifierMutex locks access to all of the global notifier state.
 */

static pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t notifierMutex     = PTHREAD_MUTEX_INITIALIZER;
/*
 * The following static indicates if the notifier thread is running.
 *
 * You must hold the notifierInitMutex before accessing this variable.
 */

static int notifierThreadRunning = 0;







|
|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

static int triggerPipe = -1;

/*
 * The notifierMutex locks access to all of the global notifier state.
 */

pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t notifierMutex     = PTHREAD_MUTEX_INITIALIZER;
/*
 * The following static indicates if the notifier thread is running.
 *
 * You must hold the notifierInitMutex before accessing this variable.
 */

static int notifierThreadRunning = 0;

Changes to unix/tclUnixPipe.c.

406
407
408
409
410
411
412

413
414
415
416
417
418
419
 *
 * Side effects:
 *	A process is created.
 *
 *---------------------------------------------------------------------------
 */


int
TclpCreateProcess(
    Tcl_Interp *interp,		/* Interpreter in which to leave errors that
				 * occurred when creating the child process.
				 * Error messages from the child process
				 * itself are sent to errorFile. */
    int argc,			/* Number of arguments in following array. */







>







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
 *
 * Side effects:
 *	A process is created.
 *
 *---------------------------------------------------------------------------
 */

    /* ARGSUSED */
int
TclpCreateProcess(
    Tcl_Interp *interp,		/* Interpreter in which to leave errors that
				 * occurred when creating the child process.
				 * Error messages from the child process
				 * itself are sent to errorFile. */
    int argc,			/* Number of arguments in following array. */
884
885
886
887
888
889
890

891
892
893
894
895
896
897
 *
 * Side effects:
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */


static int
PipeBlockModeProc(
    ClientData instanceData,	/* Pipe state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{







>







885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
 *
 * Side effects:
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
PipeBlockModeProc(
    ClientData instanceData,	/* Pipe state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
927
928
929
930
931
932
933

934
935
936
937
938
939
940
 *
 * Side effects:
 *	Closes the command pipeline channel.
 *
 *----------------------------------------------------------------------
 */


static int
PipeCloseProc(
    ClientData instanceData,	/* The pipe to close. */
    Tcl_Interp *interp)		/* For error reporting. */
{
    PipeState *pipePtr;
    Tcl_Channel errChan;







>







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
 *
 * Side effects:
 *	Closes the command pipeline channel.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
PipeCloseProc(
    ClientData instanceData,	/* The pipe to close. */
    Tcl_Interp *interp)		/* For error reporting. */
{
    PipeState *pipePtr;
    Tcl_Channel errChan;
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_PidObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{







>







1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_PidObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{

Changes to unix/tclUnixPort.h.

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
/*
 * tclUnixPort.h --
 *
 *	This header file handles porting issues that occur because of
 *	differences between systems. It reads in UNIX-related header files and
 *	sets up UNIX-related macros for Tcl's UNIX core. It should be the only

 *	file that contains #ifdefs to handle different flavors of UNIX. This
 *	file sets up the union of all UNIX-related things needed by any of the
 *	Tcl core files. This file depends on configuration #defines such as
 *	NO_DIRENT_H that are set up by the "configure" script.
 *
 *	Much of the material in this file was originally contributed by Karl
 *	Lehenbauer, Mark Diekhans and Peter da Silva.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLUNIXPORT
#define _TCLUNIXPORT

/*
 *---------------------------------------------------------------------------



|
|
|
>
|
|
|
|

|
|




|
|







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
/*
 * tclUnixPort.h --
 *
 *	This header file handles porting issues that occur because
 *	of differences between systems.  It reads in UNIX-related
 *	header files and sets up UNIX-related macros for Tcl's UNIX
 *	core.  It should be the only file that contains #ifdefs to
 *	handle different flavors of UNIX.  This file sets up the
 *	union of all UNIX-related things needed by any of the Tcl
 *	core files.  This file depends on configuration #defines such
 *	as NO_DIRENT_H that are set up by the "configure" script.
 *
 *	Much of the material in this file was originally contributed
 *	by Karl Lehenbauer, Mark Diekhans and Peter da Silva.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLUNIXPORT
#define _TCLUNIXPORT

/*
 *---------------------------------------------------------------------------
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723
724
725
#else
typedef off_t		Tcl_SeekOffset;
#   define TclOSseek		lseek
#   define TclOSopen		open
#endif

#ifdef __CYGWIN__
#ifdef __cplusplus
extern "C" {
#endif
    /* Make some symbols available without including <windows.h> */
#   define DWORD unsigned int
#   define CP_UTF8 65001
#   define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
#   define HANDLE void *
#   define HINSTANCE void *
#   define HMODULE void *
#   define MAX_PATH 260
#   define SOCKET unsigned int
#   define WSAEWOULDBLOCK 10035
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wignored-attributes"
#endif
    __declspec(dllimport) extern __stdcall int GetModuleHandleExW(unsigned int, const void *, void *);
    __declspec(dllimport) extern __stdcall int GetModuleFileNameW(void *, const void *, int);
    __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const void *, int,
	    char *, int, const char *, void *);

    __declspec(dllimport) extern int cygwin_conv_path(int, const void *, void *, int);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
/* On Cygwin, the environment is imported from the Cygwin DLL. */
#ifndef __x86_64__
#   define environ __cygwin_environ
    extern char **__cygwin_environ;
#endif
#   define timezone _timezone
    extern int TclOSstat(const char *name, void *statBuf);
    extern int TclOSlstat(const char *name, void *statBuf);
#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
#   define TclOSstat(name, buf) stat64(name, (struct stat64 *)buf)
#   define TclOSlstat(name,buf) lstat64(name, (struct stat64 *)buf)
#else
#   define TclOSstat(name, buf) stat(name, (struct stat *)buf)
#   define TclOSlstat(name, buf) lstat(name, (struct stat *)buf)
#endif

/*
 *---------------------------------------------------------------------------
 * Miscellaneous includes that might be missing.
 *---------------------------------------------------------------------------
 */

#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#   include <sys/select.h>
#endif
#include <sys/stat.h>
#if TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#ifdef HAVE_SYS_TIME_H
#   include <sys/time.h>
#else
#   include <time.h>
#endif
#endif
#ifndef NO_SYS_WAIT_H
#   include <sys/wait.h>
#endif
#ifdef HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#ifdef NO_LIMITS_H
#   include "../compat/limits.h"
#else
#   include <limits.h>
#endif
#ifdef HAVE_STDINT_H
#   include <stdint.h>
#endif
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#else
#   include "../compat/unistd.h"
#endif

extern int TclUnixSetBlockingMode(int fd, int mode);

#include <utime.h>

/*
 *---------------------------------------------------------------------------
 * Socket support stuff: This likely needs more work to parameterize for each
 * system.
 *---------------------------------------------------------------------------
 */

#include <sys/socket.h>		/* struct sockaddr, SOCK_STREAM, ... */
#ifndef NO_UNAME
#   include <sys/utsname.h>	/* uname system call. */
#endif
#include <netinet/in.h>		/* struct in_addr, struct sockaddr_in */
#include <arpa/inet.h>		/* inet_ntoa() */
#include <netdb.h>		/* gethostbyname() */

/*
 *---------------------------------------------------------------------------
 * Some platforms (e.g. SunOS) don't define FLT_MAX and FLT_MIN, so we look
 * for an alternative definition. If no other alternative is available we use
 * a reasonable guess.
 *---------------------------------------------------------------------------
 */

#ifndef NO_FLOAT_H
#   include <float.h>
#else
#ifndef NO_VALUES_H
#   include <values.h>
#endif
#endif

#ifndef FLT_MAX
#   ifdef MAXFLOAT
#	define FLT_MAX	MAXFLOAT
#   else
#	define FLT_MAX	3.402823466E+38F
#   endif
#endif
#ifndef FLT_MIN
#   ifdef MINFLOAT
#	define FLT_MIN	MINFLOAT
#   else
#	define FLT_MIN	1.175494351E-38F
#   endif
#endif

/*
 *---------------------------------------------------------------------------
 * NeXT doesn't define O_NONBLOCK, so #define it here if necessary.
 *---------------------------------------------------------------------------
 */

#ifndef O_NONBLOCK
#   define O_NONBLOCK 0x80
#endif

/*
 *---------------------------------------------------------------------------
 * The type of the status returned by wait varies from UNIX system to UNIX
 * system. The macro below defines it:
 *---------------------------------------------------------------------------
 */

#ifdef _AIX
#   define WAIT_STATUS_TYPE	pid_t
#else
#ifndef NO_UNION_WAIT
#   define WAIT_STATUS_TYPE	union wait
#else
#   define WAIT_STATUS_TYPE	int
#endif
#endif

/*
 *---------------------------------------------------------------------------
 * Supply definitions for macros to query wait status, if not already defined
 * in header files above.
 *---------------------------------------------------------------------------
 */

#ifndef WIFEXITED
#   define WIFEXITED(stat)	(((*((int *) &(stat))) & 0xFF) == 0)
#endif

#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat)	(((*((int *) &(stat))) >> 8) & 0xFF)
#endif

#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) \
	(((*((int *) &(stat)))) && ((*((int *) &(stat))) \
		== ((*((int *) &(stat))) & 0x00FF)))
#endif

#ifndef WTERMSIG
#   define WTERMSIG(stat)	((*((int *) &(stat))) & 0x7F)
#endif

#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)	(((*((int *) &(stat))) & 0xFF) == 0177)
#endif

#ifndef WSTOPSIG
#   define WSTOPSIG(stat)	(((*((int *) &(stat))) >> 8) & 0xFF)
#endif

/*
 *---------------------------------------------------------------------------
 * Define constants for waitpid() system call if they aren't defined by a
 * system header file.
 *---------------------------------------------------------------------------
 */

#ifndef WNOHANG
#   define WNOHANG 1
#endif
#ifndef WUNTRACED
#   define WUNTRACED 2
#endif

/*
 *---------------------------------------------------------------------------
 * Supply macros for seek offsets, if they're not already provided by an
 * include file.
 *---------------------------------------------------------------------------
 */

#ifndef SEEK_SET
#   define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#   define SEEK_CUR 1
#endif
#ifndef SEEK_END
#   define SEEK_END 2
#endif

/*
 *---------------------------------------------------------------------------
 * The stuff below is needed by the "time" command. If this system has no
 * gettimeofday call, then must use times() instead.
 *---------------------------------------------------------------------------
 */

#ifdef NO_GETTOD
#   include <sys/times.h>
#endif

#ifdef GETTOD_NOT_DECLARED
extern int	gettimeofday(struct timeval *tp,
			    struct timezone *tzp);
#endif

/*
 *---------------------------------------------------------------------------
 * Define access mode constants if they aren't already defined.
 *---------------------------------------------------------------------------
 */

#ifndef F_OK
#   define F_OK		00
#endif
#ifndef X_OK
#   define X_OK		01
#endif
#ifndef W_OK
#   define W_OK		02
#endif
#ifndef R_OK
#   define R_OK		04
#endif

/*
 *---------------------------------------------------------------------------
 * Define FD_CLOEEXEC (the close-on-exec flag bit) if it isn't already
 * defined.
 *---------------------------------------------------------------------------
 */

#ifndef FD_CLOEXEC
#   define FD_CLOEXEC	1
#endif

/*
 *---------------------------------------------------------------------------
 * On systems without symbolic links (i.e. S_IFLNK isn't defined) define
 * "lstat" to use "stat" instead.
 *---------------------------------------------------------------------------
 */

#ifndef S_IFLNK
#   undef TclOSlstat
#   define lstat	stat
#   define lstat64	stat64
#   define TclOSlstat	TclOSstat
#endif

/*
 *---------------------------------------------------------------------------
 * Define macros to query file type bits, if they're not already defined.
 *---------------------------------------------------------------------------

 */

#ifndef S_ISREG
#   ifdef S_IFREG
#	define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)
#   else
#	define S_ISREG(m)	0
#   endif
#endif /* !S_ISREG */
#ifndef S_ISDIR
#   ifdef S_IFDIR
#	define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)
#   else
#	define S_ISDIR(m)	0
#   endif
#endif /* !S_ISDIR */
#ifndef S_ISCHR
#   ifdef S_IFCHR
#	define S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)
#   else
#	define S_ISCHR(m)	0
#   endif
#endif /* !S_ISCHR */

#ifndef S_ISBLK
#   ifdef S_IFBLK
#	define S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)
#   else
#	define S_ISBLK(m)	0
#   endif
#endif /* !S_ISBLK */

#ifndef S_ISFIFO
#   ifdef S_IFIFO
#	define S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)
#   else
#	define S_ISFIFO(m)	0
#   endif
#endif /* !S_ISFIFO */

#ifndef S_ISLNK
#   ifdef S_IFLNK
#	define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
#   else
#	define S_ISLNK(m)	0
#   endif
#endif /* !S_ISLNK */

#ifndef S_ISSOCK
#   ifdef S_IFSOCK
#	define S_ISSOCK(m)	(((m) & S_IFMT) == S_IFSOCK)
#   else
#	define S_ISSOCK(m)	0
#   endif
#endif /* !S_ISSOCK */

/*
 *---------------------------------------------------------------------------
 * Make sure that MAXPATHLEN and MAXNAMLEN are defined.
 *---------------------------------------------------------------------------
 */

#ifndef MAXPATHLEN
#   ifdef PATH_MAX
#	define MAXPATHLEN	PATH_MAX
#   else
#	define MAXPATHLEN	2048
#   endif
#endif

#ifndef MAXNAMLEN
#   ifdef NAME_MAX
#	define MAXNAMLEN	NAME_MAX
#   else
#	define MAXNAMLEN	255
#   endif
#endif

/*
 * Make sure that L_tmpnam is defined.
 */

#ifndef L_tmpnam
#   define L_tmpnam 100
#endif

/*
 *---------------------------------------------------------------------------
 * The following macro defines the type of the mask arguments to select:
 *---------------------------------------------------------------------------

 */

#ifndef NO_FD_SET
#   define SELECT_MASK	fd_set
#else /* NO_FD_SET */
#   ifndef _AIX
	typedef long	fd_mask;
#   endif /* !AIX */
#   if defined(_IBMR2)
#	define SELECT_MASK	void
#   else /* !defined(_IBMR2) */
#	define SELECT_MASK	int
#   endif /* defined(_IBMR2) */
#endif /* !NO_FD_SET */

/*
 *---------------------------------------------------------------------------
 * Define "NBBY" (number of bits per byte) if it's not already defined.
 *---------------------------------------------------------------------------
 */

#ifndef NBBY
#   define NBBY		8
#endif

/*
 *---------------------------------------------------------------------------
 * The following macro defines the number of fd_masks in an fd_set:
 *---------------------------------------------------------------------------
 */

#ifndef FD_SETSIZE
#   ifdef OPEN_MAX
#	define FD_SETSIZE	OPEN_MAX
#   else
#	define FD_SETSIZE	256
#   endif
#endif /* FD_SETSIZE */

#ifndef howmany
#   define howmany(x, y)	(((x)+((y)-1))/(y))
#endif /* !defined(howmany) */

#ifndef NFDBITS
#   define NFDBITS	NBBY*sizeof(fd_mask)
#endif /* NFDBITS */

#define MASK_SIZE	howmany(FD_SETSIZE, NFDBITS)

/*
 *---------------------------------------------------------------------------
 * Not all systems declare the errno variable in errno.h. so this file does it
 * explicitly. The list of system error messages also isn't generally declared
 * in a header file anywhere.
 *---------------------------------------------------------------------------
 */

#ifdef NO_ERRNO
extern int errno;
#endif /* NO_ERRNO */

/*
 *---------------------------------------------------------------------------
 * Not all systems declare all the errors that Tcl uses! Provide some
 * work-arounds...
 *---------------------------------------------------------------------------
 */

#ifndef EOVERFLOW
#   ifdef EFBIG
#	define EOVERFLOW	EFBIG
#   else /* !EFBIG */
#	define EOVERFLOW	EINVAL
#   endif /* EFBIG */
#endif /* EOVERFLOW */

/*
 *---------------------------------------------------------------------------
 * Variables provided by the C library:
 *---------------------------------------------------------------------------
 */

#if defined(__APPLE__) && defined(__DYNAMIC__)
#   include <crt_externs.h>
#   define environ	(*_NSGetEnviron())
#   define USE_PUTENV	1
#else
#   if defined(_sgi) || defined(__sgi)
#	define environ	_environ
#   endif
extern char **		environ;
#endif

/*
 * There is no platform-specific panic routine for Unix in the Tcl internals.
 */

#define TclpPanic ((Tcl_PanicProc *) NULL)

/*
 *---------------------------------------------------------------------------
 * Darwin specifc configure overrides.
 *---------------------------------------------------------------------------
 */

#ifdef __APPLE__

/*
 *---------------------------------------------------------------------------
 * Support for fat compiles: configure runs only once for multiple architectures
 *---------------------------------------------------------------------------
 */

#   if defined(__LP64__) && defined (NO_COREFOUNDATION_64)
#	undef HAVE_COREFOUNDATION
#   endif /* __LP64__ && NO_COREFOUNDATION_64 */
#   include <sys/cdefs.h>
#   ifdef __DARWIN_UNIX03
#	if __DARWIN_UNIX03
#	    undef HAVE_PUTENV_THAT_COPIES
#	else
#	    define HAVE_PUTENV_THAT_COPIES	1
#	endif
#   endif /* __DARWIN_UNIX03 */

/*
 * The termios configure test program relies on the configure script being run
 * from a terminal, which is not the case e.g. when configuring from Xcode.
 * Since termios is known to be present on all Mac OS X releases since 10.0,
 * override the configure defines for serial API here. [Bug 497147]
 */
#   define USE_TERMIOS 1
#   undef  USE_TERMIO
#   undef  USE_SGTTY
/*
 *---------------------------------------------------------------------------
 * Include AvailabilityMacros.h here (when available) to ensure any symbolic
 * MAC_OS_X_VERSION_* constants passed on the command line are translated.
 *---------------------------------------------------------------------------
 */

#   ifdef HAVE_AVAILABILITYMACROS_H
#	include <AvailabilityMacros.h>
#   endif

/*
 *---------------------------------------------------------------------------
 * Support for weak import.
 *---------------------------------------------------------------------------
 */

#   ifdef HAVE_WEAK_IMPORT
#	if !defined(HAVE_AVAILABILITYMACROS_H) || !defined(MAC_OS_X_VERSION_MIN_REQUIRED)
#	    undef HAVE_WEAK_IMPORT
#	else
#	    ifndef WEAK_IMPORT_ATTRIBUTE
#		define WEAK_IMPORT_ATTRIBUTE	__attribute__((weak_import))
#	    endif
#	endif
#   endif /* HAVE_WEAK_IMPORT */

/*
 *---------------------------------------------------------------------------
 * Support for MAC_OS_X_VERSION_MAX_ALLOWED define from AvailabilityMacros.h:
 * only use API available in the indicated OS version or earlier.
 *---------------------------------------------------------------------------
 */

#   ifdef MAC_OS_X_VERSION_MAX_ALLOWED
#	if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 && defined(__LP64__)
#	    undef HAVE_COREFOUNDATION
#	endif
#	if MAC_OS_X_VERSION_MAX_ALLOWED < 1040
#	    undef HAVE_OSSPINLOCKLOCK
#	    undef HAVE_PTHREAD_ATFORK
#	    undef HAVE_COPYFILE
#	endif
#	if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
#	    ifdef TCL_THREADS
		/* prior to 10.3, realpath is not threadsafe, c.f. bug 711232 */
#		define NO_REALPATH 1
#	    endif
#	    undef HAVE_LANGINFO
#	endif
#   endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
#   if defined(HAVE_COREFOUNDATION) && defined(__LP64__) && \
	    defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050
#	warning "Weak import of 64-bit CoreFoundation is not supported, will not run on Mac OS X < 10.5."
#   endif

/*
 *---------------------------------------------------------------------------
 * At present, using vfork() instead of fork() causes execve() to fail
 * intermittently on Darwin x86_64. rdar://4685553
 *---------------------------------------------------------------------------
 */

#   if defined(__x86_64__) && !defined(FIXED_RDAR_4685553)
#	undef USE_VFORK
#   endif /* __x86_64__ */
/* Workaround problems with vfork() when building with llvm-gcc-4.2 */
#   if defined (__llvm__) && \
	    (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
	    (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
#	undef USE_VFORK
#   endif /* __llvm__ */
#endif /* __APPLE__ */

/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between
 * generic and unix-specific parts of Tcl. Some of the macros may override
 * functions declared in tclInt.h.
 *---------------------------------------------------------------------------
 */

/*
 * The default platform eol translation on Unix is TCL_TRANSLATE_LF.
 */

#ifdef DJGPP
#define	TCL_PLATFORM_TRANSLATION	TCL_TRANSLATE_CRLF
typedef int socklen_t;
#else
#define	TCL_PLATFORM_TRANSLATION	TCL_TRANSLATE_LF
#endif

/*
 *---------------------------------------------------------------------------
 * The following macros have trivial definitions, allowing generic code to
 * address platform-specific issues.
 *---------------------------------------------------------------------------
 */

#define TclpReleaseFile(file)	/* Nothing. */

/*
 *---------------------------------------------------------------------------
 * The following defines wrap the system memory allocation routines.
 *---------------------------------------------------------------------------
 */

#define TclpSysAlloc(size, isBin)	malloc((size_t)(size))
#define TclpSysFree(ptr)		free((char *)(ptr))
#define TclpSysRealloc(ptr, size)	realloc((char *)(ptr), (size_t)(size))

/*
 *---------------------------------------------------------------------------
 * The following macros and declaration wrap the C runtime library functions.
 *---------------------------------------------------------------------------

 */

#define TclpExit	exit

#ifdef TCL_THREADS
#  include <pthread.h>
/* #define localtime(x)	TclpLocaltime(x)
 * #define gmtime(x)	TclpGmtime(x)    */
#   undef inet_ntoa
#   define inet_ntoa(x)	TclpInetNtoa(x)







|
<
<






<
<


<
<
<
<
|
|
|
|
>

<
<
<









|
|

|
|

<
<
<
<
<
<










|








|







|











|

<
|
|
<

<







|

<
|
|
|
<












|

|




|

|


|

<

<





|

<
|
|
<



|


|

|


|

<
|
|
<



|



|



|
<
<



|



|



|

|

<
|
|
<








|

<
|
|
<











|

<
|

<







|


|

<

<



|


|


|


|

|

<
|
|
<



|

|

<
|
|
<








|

<
|
<
>




|

|




|

|




|

|


<


|

|


<


|

|


<


|

|


<


|

|


|

<

<




|

|





|

|


|









<
|
<
>



|


|


|

|


|

<

<



|

|

<

<




|

|


<
|
|

<

|

<
|
|

<
|
|
|
<





|

<
|

<




|

|


|

<

<




|
|


|

|

|







<

<



<

<

<

<

|
|


|
|
|
|
|

<










<


<

<

|

<

<

<

<

|
|
|
|
|
|
|

<

<


<

<

|
|
|
|
|
|
|
|
|
|

|
|
|
|



|

<

<


<

<

|





|


|


|
|














|

<
|

<



|

<

<


|
|
|
|

<
|
<
>


|







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






120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162

163

164
165
166
167
168
169
170
171
172

173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202

203
204
205
206
207
208
209

210
211

212
213
214
215
216
217
218
219
220
221
222
223
224

225
226

227
228
229
230
231
232
233
234
235
236
237
238


239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255

256
257
258
259
260
261
262
263
264
265

266
267

268
269
270
271
272
273
274
275
276
277
278
279
280

281
282

283
284
285
286
287
288
289
290
291
292
293
294

295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

312
313

314
315
316
317
318
319
320

321
322

323
324
325
326
327
328
329
330
331
332

333

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364

365
366
367
368
369
370
371

372
373
374
375
376
377
378

379
380
381
382
383
384
385
386
387

388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415

416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

434

435
436
437
438
439
440
441

442

443
444
445
446
447
448
449
450
451

452
453
454

455
456
457

458
459
460

461
462
463

464
465
466
467
468
469
470

471
472

473
474
475
476
477
478
479
480
481
482
483

484

485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504

505

506
507
508

509

510

511

512
513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532

533
534

535

536
537
538

539

540

541

542
543
544
545
546
547
548
549
550

551

552
553

554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576

577
578

579

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612

613
614
615
616
617

618

619
620
621
622
623
624
625

626

627
628
629
630
631
632
633
634
635
636
637
#else
typedef off_t		Tcl_SeekOffset;
#   define TclOSseek		lseek
#   define TclOSopen		open
#endif

#ifdef __CYGWIN__



    /* Make some symbols available without including <windows.h> */
#   define DWORD unsigned int
#   define CP_UTF8 65001
#   define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
#   define HANDLE void *
#   define HINSTANCE void *


#   define SOCKET unsigned int
#   define WSAEWOULDBLOCK 10035




    __declspec(dllimport) extern __stdcall int GetModuleHandleExW(unsigned int, const char *, void *);
    __declspec(dllimport) extern __stdcall int GetModuleFileNameW(void *, const char *, int);
    __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const char *, int,
	    const char *, int, const char *, const char *);

    __declspec(dllimport) extern int cygwin_conv_path(int, const void *, void *, int);



/* On Cygwin, the environment is imported from the Cygwin DLL. */
#ifndef __x86_64__
#   define environ __cygwin_environ
    extern char **__cygwin_environ;
#endif
#   define timezone _timezone
    extern int TclOSstat(const char *name, void *statBuf);
    extern int TclOSlstat(const char *name, void *statBuf);
#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
#   define TclOSstat		stat64
#   define TclOSlstat		lstat64
#else
#   define TclOSstat		stat
#   define TclOSlstat		lstat
#endif







#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#   include <sys/select.h>
#endif
#include <sys/stat.h>
#if TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#if HAVE_SYS_TIME_H
#   include <sys/time.h>
#else
#   include <time.h>
#endif
#endif
#ifndef NO_SYS_WAIT_H
#   include <sys/wait.h>
#endif
#if HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#ifdef NO_LIMITS_H
#   include "../compat/limits.h"
#else
#   include <limits.h>
#endif
#if HAVE_STDINT_H
#   include <stdint.h>
#endif
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#else
#   include "../compat/unistd.h"
#endif

extern int TclUnixSetBlockingMode(int fd, int mode);

#include <utime.h>

/*

 * Socket support stuff: This likely needs more work to parameterize for
 * each system.

 */

#include <sys/socket.h>		/* struct sockaddr, SOCK_STREAM, ... */
#ifndef NO_UNAME
#   include <sys/utsname.h>	/* uname system call. */
#endif
#include <netinet/in.h>		/* struct in_addr, struct sockaddr_in */
#include <arpa/inet.h>		/* inet_ntoa() */
#include <netdb.h>		/* gethostbyname() */

/*

 * Some platforms (e.g. SunOS) don't define FLT_MAX and FLT_MIN, so we
 * look for an alternative definition.  If no other alternative is available
 * we use a reasonable guess.

 */

#ifndef NO_FLOAT_H
#   include <float.h>
#else
#ifndef NO_VALUES_H
#   include <values.h>
#endif
#endif

#ifndef FLT_MAX
#   ifdef MAXFLOAT
#	define FLT_MAX MAXFLOAT
#   else
#	define FLT_MAX 3.402823466E+38F
#   endif
#endif
#ifndef FLT_MIN
#   ifdef MINFLOAT
#	define FLT_MIN MINFLOAT
#   else
#	define FLT_MIN 1.175494351E-38F
#   endif
#endif

/*

 * NeXT doesn't define O_NONBLOCK, so #define it here if necessary.

 */

#ifndef O_NONBLOCK
#   define O_NONBLOCK 0x80
#endif

/*

 * The type of the status returned by wait varies from UNIX system
 * to UNIX system.  The macro below defines it:

 */

#ifdef _AIX
#   define WAIT_STATUS_TYPE pid_t
#else
#ifndef NO_UNION_WAIT
#   define WAIT_STATUS_TYPE union wait
#else
#   define WAIT_STATUS_TYPE int
#endif
#endif

/*

 * Supply definitions for macros to query wait status, if not already
 * defined in header files above.

 */

#ifndef WIFEXITED
#   define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xff) == 0)
#endif

#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
#endif

#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff)))


#endif

#ifndef WTERMSIG
#   define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7f)
#endif

#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)  (((*((int *) &(stat))) & 0xff) == 0177)
#endif

#ifndef WSTOPSIG
#   define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xff)
#endif

/*

 * Define constants for waitpid() system call if they aren't defined
 * by a system header file.

 */

#ifndef WNOHANG
#   define WNOHANG 1
#endif
#ifndef WUNTRACED
#   define WUNTRACED 2
#endif

/*

 * Supply macros for seek offsets, if they're not already provided by
 * an include file.

 */

#ifndef SEEK_SET
#   define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#   define SEEK_CUR 1
#endif
#ifndef SEEK_END
#   define SEEK_END 2
#endif

/*

 * The stuff below is needed by the "time" command.  If this system has no
 * gettimeofday call, then must use times() instead.

 */

#ifdef NO_GETTOD
#   include <sys/times.h>
#endif

#ifdef GETTOD_NOT_DECLARED
extern int		gettimeofday (struct timeval *tp,
			    struct timezone *tzp);
#endif

/*

 * Define access mode constants if they aren't already defined.

 */

#ifndef F_OK
#    define F_OK 00
#endif
#ifndef X_OK
#    define X_OK 01
#endif
#ifndef W_OK
#    define W_OK 02
#endif
#ifndef R_OK
#    define R_OK 04
#endif

/*

 * Define FD_CLOEEXEC (the close-on-exec flag bit) if it isn't
 * already defined.

 */

#ifndef FD_CLOEXEC
#   define FD_CLOEXEC 1
#endif

/*

 * On systems without symbolic links (i.e. S_IFLNK isn't defined)
 * define "lstat" to use "stat" instead.

 */

#ifndef S_IFLNK
#   undef TclOSlstat
#   define lstat	stat
#   define lstat64	stat64
#   define TclOSlstat	TclOSstat
#endif

/*

 * Define macros to query file type bits, if they're not already

 * defined.
 */

#ifndef S_ISREG
#   ifdef S_IFREG
#       define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#   else
#       define S_ISREG(m) 0
#   endif
#endif /* !S_ISREG */
#ifndef S_ISDIR
#   ifdef S_IFDIR
#       define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#   else
#       define S_ISDIR(m) 0
#   endif
#endif /* !S_ISDIR */
#ifndef S_ISCHR
#   ifdef S_IFCHR
#       define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#   else
#       define S_ISCHR(m) 0
#   endif
#endif /* !S_ISCHR */

#ifndef S_ISBLK
#   ifdef S_IFBLK
#       define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#   else
#       define S_ISBLK(m) 0
#   endif
#endif /* !S_ISBLK */

#ifndef S_ISFIFO
#   ifdef S_IFIFO
#       define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#   else
#       define S_ISFIFO(m) 0
#   endif
#endif /* !S_ISFIFO */

#ifndef S_ISLNK
#   ifdef S_IFLNK
#       define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#   else
#       define S_ISLNK(m) 0
#   endif
#endif /* !S_ISLNK */

#ifndef S_ISSOCK
#   ifdef S_IFSOCK
#       define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#   else
#       define S_ISSOCK(m) 0
#   endif
#endif /* !S_ISSOCK */

/*

 * Make sure that MAXPATHLEN and MAXNAMLEN are defined.

 */

#ifndef MAXPATHLEN
#   ifdef PATH_MAX
#       define MAXPATHLEN PATH_MAX
#   else
#       define MAXPATHLEN 2048
#   endif
#endif

#ifndef MAXNAMLEN
#   ifdef NAME_MAX
#	define MAXNAMLEN NAME_MAX
#   else
#	define MAXNAMLEN 255
#   endif
#endif

/*
 * Make sure that L_tmpnam is defined.
 */

#ifndef L_tmpnam
#   define L_tmpnam 100
#endif

/*

 * The following macro defines the type of the mask arguments to

 * select:
 */

#ifndef NO_FD_SET
#   define SELECT_MASK fd_set
#else /* NO_FD_SET */
#   ifndef _AIX
	typedef long fd_mask;
#   endif /* !AIX */
#   if defined(_IBMR2)
#	define SELECT_MASK void
#   else /* !defined(_IBMR2) */
#	define SELECT_MASK int
#   endif /* defined(_IBMR2) */
#endif /* !NO_FD_SET */

/*

 * Define "NBBY" (number of bits per byte) if it's not already defined.

 */

#ifndef NBBY
#   define NBBY 8
#endif

/*

 * The following macro defines the number of fd_masks in an fd_set:

 */

#ifndef FD_SETSIZE
#   ifdef OPEN_MAX
#	define FD_SETSIZE OPEN_MAX
#   else
#	define FD_SETSIZE 256
#   endif
#endif /* FD_SETSIZE */

#if !defined(howmany)
#   define howmany(x, y) (((x)+((y)-1))/(y))
#endif /* !defined(howmany) */

#ifndef NFDBITS
#   define NFDBITS NBBY*sizeof(fd_mask)
#endif /* NFDBITS */

#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS)

/*

 * Not all systems declare the errno variable in errno.h. so this
 * file does it explicitly.  The list of system error messages also
 * isn't generally declared in a header file anywhere.

 */

#ifdef NO_ERRNO
extern int errno;
#endif /* NO_ERRNO */

/*

 * Not all systems declare all the errors that Tcl uses!  Provide some
 * work-arounds...

 */

#ifndef EOVERFLOW
#   ifdef EFBIG
#	define EOVERFLOW EFBIG
#   else /* !EFBIG */
#	define EOVERFLOW EINVAL
#   endif /* EFBIG */
#endif /* EOVERFLOW */

/*

 * Variables provided by the C library:

 */

#if defined(__APPLE__) && defined(__DYNAMIC__)
#   include <crt_externs.h>
#   define environ (*_NSGetEnviron())
#   define USE_PUTENV 1
#else
#   if defined(_sgi) || defined(__sgi)
#       define environ _environ
#   endif
extern char **environ;
#endif

/*
 * There is no platform-specific panic routine for Unix in the Tcl internals.
 */

#define TclpPanic ((Tcl_PanicProc *) NULL)

/*

 * Darwin specifc configure overrides.

 */

#ifdef __APPLE__

/*

 * Support for fat compiles: configure runs only once for multiple architectures

 */

#   if defined(__LP64__) && defined (NO_COREFOUNDATION_64)
#       undef HAVE_COREFOUNDATION
#    endif /* __LP64__ && NO_COREFOUNDATION_64 */
#   include <sys/cdefs.h>
#   ifdef __DARWIN_UNIX03
#       if __DARWIN_UNIX03
#           undef HAVE_PUTENV_THAT_COPIES
#       else
#           define HAVE_PUTENV_THAT_COPIES 1
#       endif
#   endif /* __DARWIN_UNIX03 */

/*
 * The termios configure test program relies on the configure script being run
 * from a terminal, which is not the case e.g. when configuring from Xcode.
 * Since termios is known to be present on all Mac OS X releases since 10.0,
 * override the configure defines for serial API here. [Bug 497147]
 */
#   define USE_TERMIOS 1
#   undef  USE_TERMIO
#   undef  USE_SGTTY
/*

 * Include AvailabilityMacros.h here (when available) to ensure any symbolic
 * MAC_OS_X_VERSION_* constants passed on the command line are translated.

 */

#   ifdef HAVE_AVAILABILITYMACROS_H
#       include <AvailabilityMacros.h>
#   endif

/*

 * Support for weak import.

 */

#   ifdef HAVE_WEAK_IMPORT
#       if !defined(HAVE_AVAILABILITYMACROS_H) || !defined(MAC_OS_X_VERSION_MIN_REQUIRED)
#           undef HAVE_WEAK_IMPORT
#       else
#           ifndef WEAK_IMPORT_ATTRIBUTE
#               define WEAK_IMPORT_ATTRIBUTE __attribute__((weak_import))
#           endif
#       endif
#   endif /* HAVE_WEAK_IMPORT */

/*

 * Support for MAC_OS_X_VERSION_MAX_ALLOWED define from AvailabilityMacros.h:
 * only use API available in the indicated OS version or earlier.

 */

#   ifdef MAC_OS_X_VERSION_MAX_ALLOWED
#       if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 && defined(__LP64__)
#           undef HAVE_COREFOUNDATION
#       endif
#       if MAC_OS_X_VERSION_MAX_ALLOWED < 1040
#           undef HAVE_OSSPINLOCKLOCK
#           undef HAVE_PTHREAD_ATFORK
#           undef HAVE_COPYFILE
#       endif
#       if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
#           ifdef TCL_THREADS
		/* prior to 10.3, realpath is not threadsafe, c.f. bug 711232 */
#               define NO_REALPATH 1
#           endif
#           undef HAVE_LANGINFO
#       endif
#   endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
#   if defined(HAVE_COREFOUNDATION) && defined(__LP64__) && \
	    defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050
#       warning "Weak import of 64-bit CoreFoundation is not supported, will not run on Mac OS X < 10.5."
#   endif

/*

 * At present, using vfork() instead of fork() causes execve() to fail
 * intermittently on Darwin x86_64. rdar://4685553

 */

#   if defined(__x86_64__) && !defined(FIXED_RDAR_4685553)
#       undef USE_VFORK
#   endif /* __x86_64__ */
/* Workaround problems with vfork() when building with llvm-gcc-4.2 */
#   if defined (__llvm__) && \
	    (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
	    (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
#       undef USE_VFORK
#   endif /* __llvm__ */
#endif /* __APPLE__ */

/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between 
 * generic and unix-specific parts of Tcl.  Some of the macros may override 
 * functions declared in tclInt.h.
 *---------------------------------------------------------------------------
 */

/*
 * The default platform eol translation on Unix is TCL_TRANSLATE_LF.
 */

#ifdef DJGPP
#define	TCL_PLATFORM_TRANSLATION	TCL_TRANSLATE_CRLF
typedef int socklen_t;
#else
#define	TCL_PLATFORM_TRANSLATION	TCL_TRANSLATE_LF
#endif

/*

 * The following macros have trivial definitions, allowing generic code to 
 * address platform-specific issues.

 */

#define TclpReleaseFile(file)	/* Nothing. */

/*

 * The following defines wrap the system memory allocation routines.

 */

#define TclpSysAlloc(size, isBin)	malloc((size_t)size)
#define TclpSysFree(ptr)		free((char*)ptr)
#define TclpSysRealloc(ptr, size)	realloc((char*)ptr, (size_t)size)

/*

 * The following macros and declaration wrap the C runtime library

 * functions.
 */

#define TclpExit		exit

#ifdef TCL_THREADS
#  include <pthread.h>
/* #define localtime(x)	TclpLocaltime(x)
 * #define gmtime(x)	TclpGmtime(x)    */
#   undef inet_ntoa
#   define inet_ntoa(x)	TclpInetNtoa(x)
737
738
739
740
741
742
743
744
745
746
747

748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
#	    define TclpPthreadGetAttrs	pthread_getattr_np
#	    ifdef GETATTRNP_NOT_DECLARED
extern int pthread_getattr_np (pthread_t, pthread_attr_t *);
#	    endif
#	endif /* HAVE_PTHREAD_GETATTR_NP */
#   endif /* HAVE_PTHREAD_ATTR_GET_NP */
#endif /* TCL_THREADS */

/*
 *---------------------------------------------------------------------------
 * Set of MT-safe implementations of some known-to-be-MT-unsafe library calls.

 * Instead of returning pointers to the static storage, those return pointers

 * to the TSD data.
 *---------------------------------------------------------------------------
 */

#include <grp.h>

extern struct passwd*  TclpGetPwNam(const char *name);
extern struct group*   TclpGetGrNam(const char *name);
extern struct passwd*  TclpGetPwUid(uid_t uid);
extern struct group*   TclpGetGrGid(gid_t gid);
extern struct hostent* TclpGetHostByName(const char *name);
extern struct hostent* TclpGetHostByAddr(const char *addr, int length, int type);

#endif /* _TCLUNIXPORT */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|

<
|
>
|
>

<












<
<
<
<
<
<
<
<
649
650
651
652
653
654
655
656
657

658
659
660
661
662

663
664
665
666
667
668
669
670
671
672
673
674








#	    define TclpPthreadGetAttrs	pthread_getattr_np
#	    ifdef GETATTRNP_NOT_DECLARED
extern int pthread_getattr_np (pthread_t, pthread_attr_t *);
#	    endif
#	endif /* HAVE_PTHREAD_GETATTR_NP */
#   endif /* HAVE_PTHREAD_ATTR_GET_NP */
#endif /* TCL_THREADS */

/*

 * Set of MT-safe implementations of some
 * known-to-be-MT-unsafe library calls.
 * Instead of returning pointers to the
 * static storage, those return pointers
 * to the TSD data.

 */

#include <grp.h>

extern struct passwd*  TclpGetPwNam(const char *name);
extern struct group*   TclpGetGrNam(const char *name);
extern struct passwd*  TclpGetPwUid(uid_t uid);
extern struct group*   TclpGetGrGid(gid_t gid);
extern struct hostent* TclpGetHostByName(const char *name);
extern struct hostent* TclpGetHostByAddr(const char *addr, int length, int type);

#endif /* _TCLUNIXPORT */








Changes to unix/tclUnixThrd.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 * tclUnixThrd.h --
 *
 *      This header file defines things for thread support.
 *
 * Copyright (c) 1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLUNIXTHRD
#define _TCLUNIXTHRD

#ifdef TCL_THREADS


#endif /* TCL_THREADS */










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 * tclUnixThrd.h --
 *
 *      This header file defines things for thread support.
 *
 * Copyright (c) 1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
 
#ifndef _TCLUNIXTHRD
#define _TCLUNIXTHRD

#ifdef TCL_THREADS


#endif /* TCL_THREADS */

Changes to unix/tclUnixTime.c.

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
120
121
122
123
124
125
126
127
128
{
    return time(NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetMicroseconds --
 *
 *	This procedure returns the number of microseconds from the epoch.
 *	On most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
 *
 * Results:
 *	Number of microseconds from the epoch.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetMicroseconds(void)
{
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    return ((Tcl_WideInt)time.sec)*1000000 + time.usec;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --
 *
 *	This procedure returns a value that represents the highest resolution
 *	clock available on the system. There are no garantees on what the
 *	resolution will be. In Tcl we will call this value a "click". The
 *	start time is also system dependent.
 *
 * Results:
 *	Number of clicks from some start time.
 *
 * Side effects:
 *	None.
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|







83
84
85
86
87
88
89


























90
91
92
93
94
95
96
97
98
99
100
101
102
{
    return time(NULL);
}

/*
 *----------------------------------------------------------------------
 *


























 * TclpGetClicks --
 *
 *	This procedure returns a value that represents the highest resolution
 *	clock available on the system. There are no garantees on what the
 *	resolution will be. In Tcl we will call this value a "click". The
 *	start time is also system dependant.
 *
 * Results:
 *	Number of clicks from some start time.
 *
 * Side effects:
 *	None.
 *
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 *-----------------------------------------------------------------------------
 *
 * TclpGetWideClicks --
 *
 *	This procedure returns a WideInt value that represents the highest
 *	resolution clock available on the system. There are no garantees on
 *	what the resolution will be. In Tcl we will call this value a "click".
 *	The start time is also system dependent.
 *
 * Results:
 *	Number of WideInt clicks from some start time.
 *
 * Side effects:
 *	None.
 *







|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
 *-----------------------------------------------------------------------------
 *
 * TclpGetWideClicks --
 *
 *	This procedure returns a WideInt value that represents the highest
 *	resolution clock available on the system. There are no garantees on
 *	what the resolution will be. In Tcl we will call this value a "click".
 *	The start time is also system dependant.
 *
 * Results:
 *	Number of WideInt clicks from some start time.
 *
 * Side effects:
 *	None.
 *
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

    if (tclGetTimeProcPtr != NativeGetTime) {
	nsec = clicks * 1000;
    } else {
#ifdef MAC_OSX_TCL
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;

	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
	} else {
	    nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
	}
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
    }

    return nsec;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpWideClickInMicrosec --
 *
 *	This procedure return scale to convert click values from the
 *	TclpGetWideClicks native resolution to microsecond resolution
 *	and back.
 *
 * Results:
 * 	1 click in microseconds as double.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (tclGetTimeProcPtr != NativeGetTime) {
	return 1.0;
    } else {
#ifdef MAC_OSX_TCL
	static int initialized = 0;
	static double scale = 0.0;

	if (initialized) {
	    return scale;
	} else {
	    mach_timebase_info_data_t tb;

	    mach_timebase_info(&tb);
	    /* value of tb.numer / tb.denom = 1 click in nanoseconds */
	    scale = ((double)tb.numer) / tb.denom / 1000;
	    initialized = 1;
	    return scale;
	}
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
    }
}
#endif /* TCL_WIDE_CLICKS */

/*
 *----------------------------------------------------------------------
 *
 * TclpGetTimeZone --
 *







|
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221













































222
223
224
225
226
227
228

    if (tclGetTimeProcPtr != NativeGetTime) {
	nsec = clicks * 1000;
    } else {
#ifdef MAC_OSX_TCL
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;
	
	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
	} else {
	    nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
	}
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
    }

    return nsec;
}













































#endif /* TCL_WIDE_CLICKS */

/*
 *----------------------------------------------------------------------
 *
 * TclpGetTimeZone --
 *

Changes to unix/tclXtTest.c.

1
2
3
4
5
6
7
8
/*
 * tclXtTest.c --
 *
 *	Contains commands for Xt notifier specific tests on Unix.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
|







1
2
3
4
5
6
7
8
/* 
 * tclXtTest.c --
 *
 *	Contains commands for Xt notifier specific tests on Unix.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 *----------------------------------------------------------------------
 */

int
Tclxttest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
	return TCL_ERROR;
    }
    XtToolkitInitialize();
    InitNotifier();
    Tcl_CreateCommand(interp, "testeventloop", TesteventloopCmd,
            (ClientData) 0, NULL);
    return TCL_OK;







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 *----------------------------------------------------------------------
 */

int
Tclxttest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
    XtToolkitInitialize();
    InitNotifier();
    Tcl_CreateCommand(interp, "testeventloop", TesteventloopCmd,
            (ClientData) 0, NULL);
    return TCL_OK;

Changes to win/Makefile.in.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

prefix			= @prefix@
exec_prefix		= @exec_prefix@
bindir			= @bindir@
libdir			= @libdir@
includedir		= @includedir@
datarootdir		= @datarootdir@
runstatedir		= @runstatedir@
mandir			= @mandir@

# The following definition can be set to non-null for special systems like AFS
# with replication. It allows the pathnames used for installation to be
# different than those used for actually reference files at run-time.
# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT	=







<







19
20
21
22
23
24
25

26
27
28
29
30
31
32

prefix			= @prefix@
exec_prefix		= @exec_prefix@
bindir			= @bindir@
libdir			= @libdir@
includedir		= @includedir@
datarootdir		= @datarootdir@

mandir			= @mandir@

# The following definition can be set to non-null for special systems like AFS
# with replication. It allows the pathnames used for installation to be
# different than those used for actually reference files at run-time.
# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT	=
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157











158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
CFLAGS_OPTIMIZE	= @CFLAGS_OPTIMIZE@

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS = 		$(CFLAGS_DEBUG)
#CFLAGS = 		$(CFLAGS_OPTIMIZE)
#CFLAGS = 		$(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS = 		@CFLAGS@ @CFLAGS_DEFAULT@ -D_ATL_XP_TARGETING=1 -D__USE_MINGW_ANSI_STDIO=0

# To compile without backward compatibility and deprecated code uncomment the
# following
NO_DEPRECATED_FLAGS	=
#NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED

# To enable compilation debugging reverse the comment characters on one of the
# following lines.
COMPILE_DEBUG_FLAGS =
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS

# Special compiler flags to use when building man2tcl on Windows.
MAN2TCLFLAGS =		@MAN2TCLFLAGS@

SRC_DIR			= @srcdir@
ROOT_DIR		= @srcdir@/..
TOP_DIR			= $(shell cd @srcdir@/..; pwd -W 2>/dev/null || pwd -P)
GENERIC_DIR		= $(TOP_DIR)/generic
TOMMATH_DIR		= $(TOP_DIR)/libtommath
WIN_DIR			= $(TOP_DIR)/win
COMPAT_DIR		= $(TOP_DIR)/compat

# Converts a POSIX path to a Windows native path.
CYGPATH			= @CYGPATH@

libdir_native	= $(shell $(CYGPATH) '$(libdir)')
bindir_native	= $(shell $(CYGPATH) '$(bindir)')
includedir_native = $(shell $(CYGPATH) '$(includedir)')
mandir_native = $(shell $(CYGPATH) '$(mandir)')
TCL_LIBRARY_NATIVE	= $(shell $(CYGPATH) '$(TCL_LIBRARY)')
GENERIC_DIR_NATIVE	= $(shell $(CYGPATH) '$(GENERIC_DIR)')
TOMMATH_DIR_NATIVE	= $(shell $(CYGPATH) '$(TOMMATH_DIR)')
WIN_DIR_NATIVE		= $(shell $(CYGPATH) '$(WIN_DIR)')
ROOT_DIR_NATIVE		= $(shell $(CYGPATH) '$(ROOT_DIR)')
ROOT_DIR_WIN_NATIVE	= $(shell cd '$(ROOT_DIR)' ; pwd -W 2>/dev/null || pwd -P)
#GENERIC_DIR_NATIVE	= $(GENERIC_DIR)
#TOMMATH_DIR_NATIVE	= $(TOMMATH_DIR)
#WIN_DIR_NATIVE		= $(WIN_DIR)
#ROOT_DIR_NATIVE		= $(ROOT_DIR)

# Fully qualify library path so that `make test`
# does not depend on the current directory.
LIBRARY_DIR1		= $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd -P)
LIBRARY_DIR             = $(shell $(CYGPATH) '$(LIBRARY_DIR1)')
DLLSUFFIX		= @DLLSUFFIX@
LIBSUFFIX		= @LIBSUFFIX@
EXESUFFIX		= @EXESUFFIX@

VER			= @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@
DOTVER			= @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@
DDEVER			= @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@
DDEDOTVER		= @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@
REGVER			= @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@
REGDOTVER		= @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@

TCL_STUB_LIB_FILE	= @TCL_STUB_LIB_FILE@
TCL_DLL_FILE		= @TCL_DLL_FILE@
TCL_LIB_FILE		= @TCL_LIB_FILE@
DDE_DLL_FILE		= tcldde$(DDEVER)${DLLSUFFIX}
DDE_LIB_FILE		= @LIBPREFIX@tcldde$(DDEVER)${DLLSUFFIX}${LIBSUFFIX}
REG_DLL_FILE		= tclreg$(REGVER)${DLLSUFFIX}
REG_LIB_FILE		= @LIBPREFIX@tclreg$(REGVER)${DLLSUFFIX}${LIBSUFFIX}
TEST_EXE_FILE		= tcltest${EXESUFFIX}
TEST_LIB_FILE		= @LIBPREFIX@tcltest$(VER)${DLLSUFFIX}${LIBSUFFIX}
TEST_LOAD_PRMS		= package ifneeded dde 1.4.3 [list load [file normalize ${DDE_DLL_FILE}] Dde];\
			  package ifneeded registry 1.3.5 [list load [file normalize ${REG_DLL_FILE}] Registry]
TEST_LOAD_FACILITIES	= $(TEST_LOAD_PRMS)

SHARED_LIBRARIES 	= $(TCL_DLL_FILE)

STATIC_LIBRARIES	= $(TCL_LIB_FILE)












TCLSH			= tclsh$(VER)${EXESUFFIX}

CAT32			= cat32$(EXEEXT)
MAN2TCL			= man2tcl$(EXEEXT)

# For cross-compiled builds, TCL_EXE is the name of a tclsh executable that is
# available *BEFORE* running make for the first time. Certain build targets
# (make genstubs, make install) need it to be available on the PATH. This
# executable should *NOT* be required just to do a normal build although
# it can be required to run make dist.
TCL_EXE			= tclsh

@SET_MAKE@

# Setting the VPATH variable to a list of paths will cause the Makefile to
# look into these paths when resolving .c to .obj dependencies.

VPATH = $(GENERIC_DIR):$(WIN_DIR):$(COMPAT_DIR):$(TOMMATH_DIR)

AR		= @AR@
RANLIB		= @RANLIB@
CC		= @CC@
RC		= @RC@
RES		= @RES@
AC_FLAGS	= @EXTRA_CFLAGS@ @DEFS@
CPPFLAGS	= @CPPFLAGS@
LDFLAGS_DEBUG   = @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
LDFLAGS		= @LDFLAGS@ @LDFLAGS_DEFAULT@
LDFLAGS_CONSOLE	= @LDFLAGS_CONSOLE@
LDFLAGS_WINDOW	= @LDFLAGS_WINDOW@
EXEEXT		= @EXEEXT@
OBJEXT		= @OBJEXT@
STLIB_LD	= @STLIB_LD@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_SUFFIX	= @SHLIB_SUFFIX@
LIBS		= @LIBS@

RMDIR		= rm -rf
MKDIR		= mkdir -p
SHELL		= @SHELL@
RM		= rm -f
COPY		= cp

CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH \
-DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \
${AC_FLAGS} ${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS}

CC_OBJNAME = @CC_OBJNAME@
CC_EXENAME = @CC_EXENAME@

STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}

TCLTEST_OBJS = \
	tclTest.$(OBJEXT) \
	tclTestObj.$(OBJEXT) \
	tclTestProcBodyObj.$(OBJEXT) \
	tclThreadTest.$(OBJEXT) \
	tclWinTest.$(OBJEXT)


GENERIC_OBJS = \
	regcomp.$(OBJEXT) \
	regexec.$(OBJEXT) \
	regfree.$(OBJEXT) \
	regerror.$(OBJEXT) \
	tclAlloc.$(OBJEXT) \







|
<
<
<
<
<












<
|
|
|
|













<







|
















|

|
<
|
<
<
<

|
>
|

>
>
>
>
>
>
>
>
>
>
>

>



<
<
<
<
<
<
<





|

















|











|
|
|














|
>







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
CFLAGS_OPTIMIZE	= @CFLAGS_OPTIMIZE@

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS = 		$(CFLAGS_DEBUG)
#CFLAGS = 		$(CFLAGS_OPTIMIZE)
#CFLAGS = 		$(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS = 		@CFLAGS@ @CFLAGS_DEFAULT@ -D_ATL_XP_TARGETING






# To enable compilation debugging reverse the comment characters on one of the
# following lines.
COMPILE_DEBUG_FLAGS =
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS

# Special compiler flags to use when building man2tcl on Windows.
MAN2TCLFLAGS =		@MAN2TCLFLAGS@

SRC_DIR			= @srcdir@
ROOT_DIR		= @srcdir@/..

GENERIC_DIR		= @srcdir@/../generic
TOMMATH_DIR		= @srcdir@/../libtommath
WIN_DIR			= @srcdir@
COMPAT_DIR		= @srcdir@/../compat

# Converts a POSIX path to a Windows native path.
CYGPATH			= @CYGPATH@

libdir_native	= $(shell $(CYGPATH) '$(libdir)')
bindir_native	= $(shell $(CYGPATH) '$(bindir)')
includedir_native = $(shell $(CYGPATH) '$(includedir)')
mandir_native = $(shell $(CYGPATH) '$(mandir)')
TCL_LIBRARY_NATIVE	= $(shell $(CYGPATH) '$(TCL_LIBRARY)')
GENERIC_DIR_NATIVE	= $(shell $(CYGPATH) '$(GENERIC_DIR)')
TOMMATH_DIR_NATIVE	= $(shell $(CYGPATH) '$(TOMMATH_DIR)')
WIN_DIR_NATIVE		= $(shell $(CYGPATH) '$(WIN_DIR)')
ROOT_DIR_NATIVE		= $(shell $(CYGPATH) '$(ROOT_DIR)')

#GENERIC_DIR_NATIVE	= $(GENERIC_DIR)
#TOMMATH_DIR_NATIVE	= $(TOMMATH_DIR)
#WIN_DIR_NATIVE		= $(WIN_DIR)
#ROOT_DIR_NATIVE		= $(ROOT_DIR)

# Fully qualify library path so that `make test`
# does not depend on the current directory.
LIBRARY_DIR1		= $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd)
LIBRARY_DIR             = $(shell $(CYGPATH) '$(LIBRARY_DIR1)')
DLLSUFFIX		= @DLLSUFFIX@
LIBSUFFIX		= @LIBSUFFIX@
EXESUFFIX		= @EXESUFFIX@

VER			= @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@
DOTVER			= @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@
DDEVER			= @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@
DDEDOTVER		= @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@
REGVER			= @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@
REGDOTVER		= @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@

TCL_STUB_LIB_FILE	= @TCL_STUB_LIB_FILE@
TCL_DLL_FILE		= @TCL_DLL_FILE@
TCL_LIB_FILE		= @TCL_LIB_FILE@
DDE_DLL_FILE		= tcldde$(DDEVER)${DLLSUFFIX}
DDE_LIB_FILE		= tcldde$(DDEVER)${LIBSUFFIX}
REG_DLL_FILE		= tclreg$(REGVER)${DLLSUFFIX}
REG_LIB_FILE		= tclreg$(REGVER)${LIBSUFFIX}

PIPE_DLL_FILE		= tclpip$(VER)${DLLSUFFIX}




SHARED_LIBRARIES 	= $(TCL_DLL_FILE) $(TCL_STUB_LIB_FILE) \
			  $(DDE_DLL_FILE) $(REG_DLL_FILE) $(PIPE_DLL_FILE)
STATIC_LIBRARIES	= $(TCL_LIB_FILE) $(REG_LIB_FILE) $(DDE_LIB_FILE)

# To compile without backward compatibility and deprecated code
# uncomment the following
NO_DEPRECATED_FLAGS	=
#NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED

# TCL_EXE is the name of a tclsh executable that is available *BEFORE* running
# make for the first time. Certain build targets (make genstubs) need it to be
# available on the PATH. This executable should *NOT* be required just to do a
# normal build although it can be required to run make dist.
TCL_EXE			= tclsh

TCLSH			= tclsh$(VER)${EXESUFFIX}
TCLTEST			= tcltest${EXEEXT}
CAT32			= cat32$(EXEEXT)
MAN2TCL			= man2tcl$(EXEEXT)








@SET_MAKE@

# Setting the VPATH variable to a list of paths will cause the Makefile to
# look into these paths when resolving .c to .obj dependencies.

VPATH = $(GENERIC_DIR):$(TOMMATH_DIR):$(WIN_DIR):$(COMPAT_DIR)

AR		= @AR@
RANLIB		= @RANLIB@
CC		= @CC@
RC		= @RC@
RES		= @RES@
AC_FLAGS	= @EXTRA_CFLAGS@ @DEFS@
CPPFLAGS	= @CPPFLAGS@
LDFLAGS_DEBUG   = @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
LDFLAGS		= @LDFLAGS@ @LDFLAGS_DEFAULT@
LDFLAGS_CONSOLE	= @LDFLAGS_CONSOLE@
LDFLAGS_WINDOW	= @LDFLAGS_WINDOW@
EXEEXT		= @EXEEXT@
OBJEXT		= @OBJEXT@
STLIB_LD	= @STLIB_LD@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@ $(LIBS)
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_SUFFIX	= @SHLIB_SUFFIX@
LIBS		= @LIBS@

RMDIR		= rm -rf
MKDIR		= mkdir -p
SHELL		= @SHELL@
RM		= rm -f
COPY		= cp

CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS}

CC_OBJNAME = @CC_OBJNAME@
CC_EXENAME = @CC_EXENAME@

STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}

TCLTEST_OBJS = \
	tclTest.$(OBJEXT) \
	tclTestObj.$(OBJEXT) \
	tclTestProcBodyObj.$(OBJEXT) \
	tclThreadTest.$(OBJEXT) \
	tclWinTest.$(OBJEXT) \
	testMain.$(OBJEXT)

GENERIC_OBJS = \
	regcomp.$(OBJEXT) \
	regexec.$(OBJEXT) \
	regfree.$(OBJEXT) \
	regerror.$(OBJEXT) \
	tclAlloc.$(OBJEXT) \
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

425


426

427
428
429
430
431
432

433
434
435
436

437



438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

465
466
467



468

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505


506
507
508
509


510
511
512
513
514








515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

TCL_OBJS = ${GENERIC_OBJS} $(TOMMATH_OBJS) ${WIN_OBJS}

TCL_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n]

all: binaries libraries doc

# Test-suite helper (can be used to test Tcl from build directory with all expected modules).
# To start from windows shell use:
#   > tcltest.cmd -verbose bps -file fileName.test
# or from mingw/msys shell:
#   $ ./tcltest -verbose bps -file fileName.test

tcltest.cmd: Makefile
	@echo 'Create tcltest.cmd helpers';
	@(\
	  echo '@echo off'; \
	  echo 'rem set LANG=en_US'; \
	  echo 'set BDP=%~dp0'; \
	  echo 'set OWD=%CD%'; \
	  echo 'cd /d %TEMP%'; \
	  echo 'rem "%BDP%\$(TCLSH)" "$(ROOT_DIR_WIN_NATIVE)/tests/all.tcl" %TESTFLAGS% -load "$(TEST_LOAD_FACILITIES)" %*'; \
	  echo '"%BDP%\$(TEST_EXE_FILE)" "$(ROOT_DIR_WIN_NATIVE)/tests/all.tcl" %TESTFLAGS% -load "$(TEST_LOAD_PRMS)" %*'; \
	  echo 'cd /d %OWD%'; \
	) > tcltest.cmd;
	@(\
	  echo '#!/bin/sh'; \
	  echo '#LANG=en_US'; \
	  echo 'BDP=$$(dirname $$(readlink -f %0))'; \
	  echo 'cd /tmp'; \
	  echo '#"$$BDP/$(TCLSH)" "$(ROOT_DIR_WIN_NATIVE)/tests/all.tcl" $$TESTFLAGS -load "$(TEST_LOAD_FACILITIES)" "$$@"'; \
	  echo '"$$BDP/$(TEST_EXE_FILE)" "$(ROOT_DIR_WIN_NATIVE)/tests/all.tcl" $$TESTFLAGS -load "$(TEST_LOAD_PRMS)" "$$@"'; \
	) > tcltest.sh;

tcltest.sh: tcltest.cmd

tcltest: binaries $(TEST_EXE_FILE) $(CAT32) tcltest.cmd




binaries: $(TCL_STUB_LIB_FILE) @LIBRARIES@ winextensions $(TCLSH)


winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE}

libraries:

doc:


$(TCLSH): $(TCLSH_OBJS) @LIBRARIES@ $(TCL_STUB_LIB_FILE) tclsh.$(RES)
	$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)

	$(COPY) tclsh.exe.manifest $(TCLSH).manifest



	@VC_MANIFEST_EMBED_EXE@

cat32.$(OBJEXT): cat.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

$(CAT32): cat32.$(OBJEXT)
	$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)

# The following targets are configured by autoconf to generate either a shared
# library or static library

${TCL_STUB_LIB_FILE}: ${STUB_OBJS}
	@$(RM) ${TCL_STUB_LIB_FILE}
	@MAKE_STUB_LIB@ ${STUB_OBJS}
	@POST_MAKE_LIB@

${TCL_DLL_FILE}: ${TCL_OBJS} tcl.$(RES)
	@$(RM) ${TCL_DLL_FILE} $(TCL_LIB_FILE)
	@MAKE_DLL@ ${TCL_OBJS} tcl.$(RES) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${TCL_DLL_FILE}.manifest
	@VC_MANIFEST_EMBED_DLL@

${TCL_LIB_FILE}: ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_LIB_FILE}
	@MAKE_LIB@ ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@POST_MAKE_LIB@


${DDE_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${DDE_OBJS}
	@MAKE_DLL@ ${DDE_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${DDE_DLL_FILE}.manifest





${REG_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${REG_OBJS}
	@MAKE_DLL@ ${REG_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${REG_DLL_FILE}.manifest

${TEST_EXE_FILE}: ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS} tclTestMain.${OBJEXT}
	@$(RM) ${TEST_EXE_FILE}
	$(CC) $(CFLAGS) $(TCLTEST_OBJS) tclTestMain.$(OBJEXT) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	$(COPY) tclsh.exe.manifest ${TEST_EXE_FILE}.manifest

# PIPE_DLL_FILE is actually an executable, don't build it like a DLL.

${PIPE_DLL_FILE}: ${PIPE_OBJS}
	@$(RM) ${PIPE_DLL_FILE}
	@MAKE_EXE@ $(CFLAGS) ${PIPE_OBJS} $(LIBS) $(LDFLAGS_CONSOLE)

# Add the object extension to the implicit rules. By default .obj is not
# automatically added.

.SUFFIXES: .${OBJEXT}
.SUFFIXES: .$(RES)
.SUFFIXES: .rc

# Special case object targets

tclTestMain.${OBJEXT}: tclAppInit.c
	$(CC) -c $(CC_SWITCHES) -DTCL_TEST -DBUILD_tcl $(EXTFLAGS) $(CC_OBJNAME) $(WIN_DIR)/tclAppInit.c

tclWinInit.${OBJEXT}: tclWinInit.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinPipe.${OBJEXT}: tclWinPipe.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl -DTCL_PIPE_DLL=\"$(PIPE_DLL_FILE)\" \
	    $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinReg.${OBJEXT}: tclWinReg.c
	$(CC) -c $(CC_SWITCHES) \


	    $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinDde.${OBJEXT}: tclWinDde.c
	$(CC) -c $(CC_SWITCHES) \


	    $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

testMain.${OBJEXT}: tclAppInit.c
	$(CC) -c $(CC_SWITCHES) -DTCL_TEST @DEPARG@ $(CC_OBJNAME)









# TIP #59, embedding of configuration information into the binary library.
#
# Part of Tcl's configuration information are the paths where it was installed
# and where it will look for its libraries (which can be different). We derive
# this information from the variables which can be overridden by the user. As
# every path can be configured separately we do not remember one general
# prefix/exec_prefix but all the different paths individually.

tclPkgConfig.${OBJEXT}: tclPkgConfig.c
	$(CC)	-c $(CC_SWITCHES)			\
		-DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR_NATIVE)\"" \
		-DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR_NATIVE)\"" \
		-DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR_NATIVE)\"" \
		-DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR_NATIVE)\"" \
		-DCFG_INSTALL_DOCDIR="\"$(MAN_INSTALL_DIR)\"" \
		\
		-DCFG_RUNTIME_LIBDIR="\"$(libdir_native)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir_native)\"" \
		-DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY_NATIVE)\"" \
		-DCFG_RUNTIME_INCDIR="\"$(includedir_native)\"" \
		-DCFG_RUNTIME_DOCDIR="\"$(mandir_native)\"" \
		-DBUILD_tcl \
		@DEPARG@ $(CC_OBJNAME)

# The following objects are part of the stub library and should not be built
# as DLL objects but none of the symbols should be exported

tclStubLib.${OBJEXT}: tclStubLib.c







<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<

|

<
>

>
>
|
>



<
|
<
>

|
|

>
|
>
>
>

















|

<


|

|


>
|

|
>
>
>

>
|

<

|
|
|
<
<
















<
<
<







|
|
>
>
|

|
|
>
>
|

|
|

>
>
>
>
>
>
>
>










|
|
|
|
|

|
|
|
|
|







383
384
385
386
387
388
389




390
391













392






393
394
395

396
397
398
399
400
401
402
403
404

405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

453
454
455
456


457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472



473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

TCL_OBJS = ${GENERIC_OBJS} $(TOMMATH_OBJS) ${WIN_OBJS}

TCL_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n]

all: binaries libraries doc





tcltest: $(TCLTEST)














binaries: @LIBRARIES@ $(TCLSH)







libraries:


doc:

winhelp: $(ROOT_DIR)/tools/man2help.tcl $(MAN2TCL)
	TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLSH) "$(ROOT_DIR_NATIVE)"/tools/man2help.tcl tcl "$(VER)" $(TCL_DOCS)
	hcw /c /e tcl.hpj

winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE}


$(MAN2TCL): $(ROOT_DIR)/tools/man2tcl.c

	$(CC) $(CFLAGS_OPTIMIZE) $(MAN2TCLFLAGS) -o $(MAN2TCL) "$(ROOT_DIR_NATIVE)"/tools/man2tcl.c

$(TCLSH): $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(TCLSH_OBJS) tclsh.$(RES)
	$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	@VC_MANIFEST_EMBED_EXE@

$(TCLTEST): $(TCL_LIB_FILE) $(TCLTEST_OBJS) $(CAT32) tclsh.$(RES)
	$(CC) $(CFLAGS) $(TCLTEST_OBJS) $(TCL_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	@VC_MANIFEST_EMBED_EXE@

cat32.$(OBJEXT): cat.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

$(CAT32): cat32.$(OBJEXT)
	$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)

# The following targets are configured by autoconf to generate either a shared
# library or static library

${TCL_STUB_LIB_FILE}: ${STUB_OBJS}
	@$(RM) ${TCL_STUB_LIB_FILE}
	@MAKE_STUB_LIB@ ${STUB_OBJS}
	@POST_MAKE_LIB@

${TCL_DLL_FILE}: ${TCL_OBJS} tcl.$(RES)
	@$(RM) ${TCL_DLL_FILE}
	@MAKE_DLL@ ${TCL_OBJS} tcl.$(RES) $(SHLIB_LD_LIBS)

	@VC_MANIFEST_EMBED_DLL@

${TCL_LIB_FILE}: ${TCL_OBJS}
	@$(RM) ${TCL_LIB_FILE}
	@MAKE_LIB@ ${TCL_OBJS}
	@POST_MAKE_LIB@

${DDE_DLL_FILE}: ${DDE_OBJS} ${TCL_STUB_LIB_FILE}
	@$(RM) ${DDE_DLL_FILE}
	@MAKE_DLL@ ${DDE_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)

${DDE_LIB_FILE}: ${DDE_OBJS} ${TCL_LIB_FILE}
	@$(RM) ${DDE_LIB_FILE}
	@MAKE_LIB@ ${DDE_OBJS} ${TCL_LIB_FILE}

${REG_DLL_FILE}: ${REG_OBJS} ${TCL_STUB_LIB_FILE}
	@$(RM) ${REG_DLL_FILE}
	@MAKE_DLL@ ${REG_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)


${REG_LIB_FILE}: ${REG_OBJS} ${TCL_LIB_FILE}
	@$(RM) ${REG_LIB_FILE}
	@MAKE_LIB@ ${REG_OBJS} ${TCL_LIB_FILE}



# PIPE_DLL_FILE is actually an executable, don't build it like a DLL.

${PIPE_DLL_FILE}: ${PIPE_OBJS}
	@$(RM) ${PIPE_DLL_FILE}
	@MAKE_EXE@ $(CFLAGS) ${PIPE_OBJS} $(LIBS) $(LDFLAGS_CONSOLE)

# Add the object extension to the implicit rules. By default .obj is not
# automatically added.

.SUFFIXES: .${OBJEXT}
.SUFFIXES: .$(RES)
.SUFFIXES: .rc

# Special case object targets




tclWinInit.${OBJEXT}: tclWinInit.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinPipe.${OBJEXT}: tclWinPipe.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl -DTCL_PIPE_DLL=\"$(PIPE_DLL_FILE)\" \
	    $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

testMain.${OBJEXT}: tclAppInit.c
	$(CC) -c $(CC_SWITCHES) -DTCL_TEST @DEPARG@ $(CC_OBJNAME)

tclTest.${OBJEXT}: tclTest.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

tclTestObj.${OBJEXT}: tclTestObj.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

tclWinTest.${OBJEXT}: tclWinTest.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

tclAppInit.${OBJEXT} : tclAppInit.c
	$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)

# The following objects should be built using the stub interfaces

tclWinReg.${OBJEXT} : tclWinReg.c
	$(CC) -c $(CC_SWITCHES) -DUSE_TCL_STUBS @DEPARG@ $(CC_OBJNAME)

tclWinDde.${OBJEXT} : tclWinDde.c
	$(CC) -c $(CC_SWITCHES) -DUSE_TCL_STUBS @DEPARG@ $(CC_OBJNAME)

# TIP #59, embedding of configuration information into the binary library.
#
# Part of Tcl's configuration information are the paths where it was installed
# and where it will look for its libraries (which can be different). We derive
# this information from the variables which can be overridden by the user. As
# every path can be configured separately we do not remember one general
# prefix/exec_prefix but all the different paths individually.

tclPkgConfig.${OBJEXT}: tclPkgConfig.c
	$(CC)	-c $(CC_SWITCHES)			\
		-DCFG_INSTALL_LIBDIR=\"$(LIB_INSTALL_DIR_NATIVE)\" \
		-DCFG_INSTALL_BINDIR=\"$(BIN_INSTALL_DIR_NATIVE)\" \
		-DCFG_INSTALL_SCRDIR=\"$(SCRIPT_INSTALL_DIR_NATIVE)\" \
		-DCFG_INSTALL_INCDIR=\"$(INCLUDE_INSTALL_DIR_NATIVE)\" \
		-DCFG_INSTALL_DOCDIR=\"$(MAN_INSTALL_DIR)\" \
		\
		-DCFG_RUNTIME_LIBDIR=\"$(libdir_native)\" \
		-DCFG_RUNTIME_BINDIR=\"$(bindir_native)\" \
		-DCFG_RUNTIME_SCRDIR=\"$(TCL_LIBRARY_NATIVE)\" \
		-DCFG_RUNTIME_INCDIR=\"$(includedir_native)\" \
		-DCFG_RUNTIME_DOCDIR=\"$(mandir_native)\" \
		-DBUILD_tcl \
		@DEPARG@ $(CC_OBJNAME)

# The following objects are part of the stub library and should not be built
# as DLL objects but none of the symbols should be exported

tclStubLib.${OBJEXT}: tclStubLib.c
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
	--no-lines \
	$(GENERIC_DIR)/tclGetDate.y

# The following target generates the file generic/tclTomMath.h. It needs to be
# run (and the results checked) after updating to a new release of libtommath.

gentommath_h:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/fix_tommath_h.tcl" \
		"$(TOMMATH_DIR_NATIVE)/tommath.h" \
		> "$(GENERIC_DIR_NATIVE)/tclTomMath.h"

install: all install-binaries install-libraries install-doc

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" ; \
	    do \
	    if [ ! -d $$i ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) $$i; \
		chmod 755 $$i; \
		else true; \
		fi; \
	    done;
	@for i in dde${DDEDOTVER} reg${REGDOTVER}; \
	    do \
	    if [ ! -d $(LIB_INSTALL_DIR)/$$i ] ; then \
		echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \
		$(MKDIR) $(LIB_INSTALL_DIR)/$$i; \
		else true; \
		fi; \
	    done;







|
|
|













|







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
	--no-lines \
	$(GENERIC_DIR)/tclGetDate.y

# The following target generates the file generic/tclTomMath.h. It needs to be
# run (and the results checked) after updating to a new release of libtommath.

gentommath_h:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)\tools\fix_tommath_h.tcl" \
		"$(TOMMATH_DIR_NATIVE)\tommath.h" \
		> "$(GENERIC_DIR_NATIVE)\tclTomMath.h"

install: all install-binaries install-libraries install-doc

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" ; \
	    do \
	    if [ ! -d $$i ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) $$i; \
		chmod 755 $$i; \
		else true; \
		fi; \
	    done;
	@for i in dde$(DDEDOTVER) reg$(REGDOTVER); \
	    do \
	    if [ ! -d $(LIB_INSTALL_DIR)/$$i ] ; then \
		echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \
		$(MKDIR) $(LIB_INSTALL_DIR)/$$i; \
		else true; \
		fi; \
	    done;
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	    if [ -f $$i ]; then \
		echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \
		$(COPY) $$i "$(LIB_INSTALL_DIR)"; \
	    fi; \
	    done
	@if [ -f $(DDE_DLL_FILE) ]; then \
	    echo Installing $(DDE_DLL_FILE); \
	    $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \
	    $(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \
		$(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \
	    fi
	@if [ -f $(DDE_LIB_FILE) ]; then \
	    echo Installing $(DDE_LIB_FILE); \
	    $(COPY) $(DDE_LIB_FILE) $(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \
	    fi
	@if [ -f $(REG_DLL_FILE) ]; then \
	    echo Installing $(REG_DLL_FILE); \
	    $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg${REGDOTVER}; \
	    $(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \
		$(LIB_INSTALL_DIR)/reg${REGDOTVER}; \
	    fi
	@if [ -f $(REG_LIB_FILE) ]; then \
	    echo Installing $(REG_LIB_FILE); \
	    $(COPY) $(REG_LIB_FILE) $(LIB_INSTALL_DIR)/reg${REGDOTVER}; \
	    fi

install-libraries: libraries install-tzdata install-msgs
	@for i in "$$($(CYGPATH) $(prefix)/lib)" "$(INCLUDE_INSTALL_DIR)" \
		$(SCRIPT_INSTALL_DIR); \
	    do \
	    if [ ! -d $$i ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) $$i; \
		else true; \
		fi; \







|

|



|



|

|



|



|







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
	    if [ -f $$i ]; then \
		echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \
		$(COPY) $$i "$(LIB_INSTALL_DIR)"; \
	    fi; \
	    done
	@if [ -f $(DDE_DLL_FILE) ]; then \
	    echo Installing $(DDE_DLL_FILE); \
	    $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde$(DDEDOTVER); \
	    $(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \
		$(LIB_INSTALL_DIR)/dde$(DDEDOTVER); \
	    fi
	@if [ -f $(DDE_LIB_FILE) ]; then \
	    echo Installing $(DDE_LIB_FILE); \
	    $(COPY) $(DDE_LIB_FILE) $(LIB_INSTALL_DIR)/dde$(DDEDOTVER); \
	    fi
	@if [ -f $(REG_DLL_FILE) ]; then \
	    echo Installing $(REG_DLL_FILE); \
	    $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg$(REGDOTVER); \
	    $(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \
		$(LIB_INSTALL_DIR)/reg$(REGDOTVER); \
	    fi
	@if [ -f $(REG_LIB_FILE) ]; then \
	    echo Installing $(REG_LIB_FILE); \
	    $(COPY) $(REG_LIB_FILE) $(LIB_INSTALL_DIR)/reg$(REGDOTVER); \
	    fi

install-libraries: libraries install-tzdata install-msgs
	@for i in $(prefix)/lib $(INCLUDE_INSTALL_DIR) \
		$(SCRIPT_INSTALL_DIR); \
	    do \
	    if [ ! -d $$i ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) $$i; \
		else true; \
		fi; \
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686

687
688
689
690
691

692
693
694
695
696
697
698
699
	    $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing library http1.0 directory";
	@for j in $(ROOT_DIR)/library/http1.0/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \
	    done;
	@echo "Installing package http 2.7.15 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/http-2.7.15.tm;
	@echo "Installing library opt0.4 directory";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.5.2 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.5.2.tm;
	@echo "Installing package tcltest 2.5.3 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/tcltest-2.5.3.tm;
	@echo "Installing package platform 1.0.18 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.18.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform/shell-1.1.4.tm;
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

install-tzdata:
	@echo "Installing time zone data"

	@$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"

install-msgs:
	@echo "Installing message catalogs"

	@$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"

install-doc: doc

# Optional target to install private headers
install-private-headers: libraries
	@for i in $(PRIVATE_INCLUDE_INSTALL_DIR); \







|
|







|
|
|
|









>
|




>
|







646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
	    $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing library http1.0 directory";
	@for j in $(ROOT_DIR)/library/http1.0/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \
	    done;
	@echo "Installing package http 2.7.14 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/http-2.7.14.tm;
	@echo "Installing library opt0.4 directory";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.5.2 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.5.2.tm;
	@echo "Installing package tcltest 2.3.8 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/tcltest-2.3.8.tm;
	@echo "Installing package platform 1.0.14 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.14.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform/shell-1.1.4.tm;
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

install-tzdata:
	@echo "Installing time zone data"
	@TCL_LIBRARY="${LIBRARY_DIR}"; export TCL_LIBRARY; \
	./$(TCLSH) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"

install-msgs:
	@echo "Installing message catalogs"
	@TCL_LIBRARY="${LIBRARY_DIR}"; export TCL_LIBRARY; \
	./$(TCLSH) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"

install-doc: doc

# Optional target to install private headers
install-private-headers: libraries
	@for i in $(PRIVATE_INCLUDE_INSTALL_DIR); \
712
713
714
715
716
717
718
719
720
721
722
723
724

725
726
727
728
729

730
731
732
733
734
735
736
	    $(COPY) "$$i" "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    done;

# Specifying TESTFLAGS on the command line is the standard way to pass args to
# tcltest, i.e.:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"

test: test-tcl

test-tcl: tcltest
	TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TEST_EXE_FILE) "$(ROOT_DIR_NATIVE)/tests/all.tcl" $(TESTFLAGS) \
	-load "$(TEST_LOAD_FACILITIES)"


# Useful target to launch a built tclsh with the proper path,...
runtest: tcltest
	@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TEST_EXE_FILE) $(TESTFLAGS) -load "$(TEST_LOAD_FACILITIES)" $(SCRIPT)


# This target can be used to run tclsh from the build directory via
# `make shell SCRIPT=foo.tcl`
shell: binaries
	@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLSH) $(SCRIPT)








<
|
<

|
|
>

|
|

|
>







702
703
704
705
706
707
708

709

710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
	    $(COPY) "$$i" "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
	    done;

# Specifying TESTFLAGS on the command line is the standard way to pass args to
# tcltest, i.e.:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"


test: binaries $(TCLTEST)

	TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLTEST) "$(ROOT_DIR_NATIVE)/tests/all.tcl" $(TESTFLAGS) \
	-load "package ifneeded dde 1.3.3 [list load [file normalize ${DDE_DLL_FILE}] dde]; \
	package ifneeded registry 1.2.2 [list load [file normalize ${REG_DLL_FILE}] registry]" | ./$(CAT32)

# Useful target to launch a built tcltest with the proper path,...
runtest: binaries $(TCLTEST)
	@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLTEST) $(TESTFLAGS) -load "package ifneeded dde 1.3.3 [list load [file normalize ${DDE_DLL_FILE}] dde]; \
	package ifneeded registry 1.2.2 [list load [file normalize ${REG_DLL_FILE}] registry]" $(SCRIPT)

# This target can be used to run tclsh from the build directory via
# `make shell SCRIPT=foo.tcl`
shell: binaries
	@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLSH) $(SCRIPT)

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
	./config.status

cleanhelp:
	$(RM) *.hlp *.cnt *.GID *.rtf man2tcl.exe

clean: cleanhelp
	$(RM) *.lib *.a *.exp *.dll *.$(RES) *.${OBJEXT} *~ \#* TAGS a.out
	$(RM) $(TCLSH) $(CAT32) $(TEST_EXE_FILE) tcltest.cmd tcltest.sh
	$(RM) *.pch *.ilk *.pdb *.zip
	$(RMDIR) *.vfs

distclean: clean
	$(RM) Makefile config.status config.cache config.log tclConfig.sh \
		tcl.hpj config.status.lineno

#
# Regenerate the stubs files.
#

$(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \
		$(GENERIC_DIR)/tclInt.decls
	@echo "Warning: tclStubInit.c may be out of date."
	@echo "Developers may want to run \"make genstubs\" to regenerate."
	@echo "This warning can be safely ignored, do not report as a bug!"

genstubs:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tcl.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclInt.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclTomMath.decls"

winhelp: $(ROOT_DIR)/tools/man2help.tcl $(MAN2TCL)
	TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	./$(TCLSH) "$(ROOT_DIR_NATIVE)"/tools/man2help.tcl tcl "$(VER)" $(TCL_DOCS)
	hcw /c /e tcl.hpj

$(MAN2TCL): $(ROOT_DIR)/tools/man2tcl.c
	$(CC) $(CFLAGS_OPTIMIZE) $(MAN2TCLFLAGS) -o $(MAN2TCL) "$(ROOT_DIR_NATIVE)"/tools/man2tcl.c

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all tcltest binaries libraries doc gendate gentommath_h install
.PHONY: install-binaries install-libraries install-tzdata install-msgs
.PHONY: install-doc install-private-headers test test-tcl runtest shell
.PHONY: gdb depend cleanhelp clean distclean packages install-packages
.PHONY: test-packages clean-packages distclean-packages genstubs html
.PHONY: html-tcl html-tk

# DO NOT DELETE THIS LINE -- make depend depends on it.







|
|
<



















|


<
<
<
<
<
<
<
<













736
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766








767
768
769
770
771
772
773
774
775
776
777
778
779
	./config.status

cleanhelp:
	$(RM) *.hlp *.cnt *.GID *.rtf man2tcl.exe

clean: cleanhelp
	$(RM) *.lib *.a *.exp *.dll *.$(RES) *.${OBJEXT} *~ \#* TAGS a.out
	$(RM) $(TCLSH) $(TCLTEST) $(CAT32)
	$(RM) *.pch *.ilk *.pdb


distclean: clean
	$(RM) Makefile config.status config.cache config.log tclConfig.sh \
		tcl.hpj config.status.lineno

#
# Regenerate the stubs files.
#

$(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \
		$(GENERIC_DIR)/tclInt.decls
	@echo "Warning: tclStubInit.c may be out of date."
	@echo "Developers may want to run \"make genstubs\" to regenerate."
	@echo "This warning can be safely ignored, do not report as a bug!"

genstubs:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tcl.decls" \
            "$(GENERIC_DIR_NATIVE)/tclInt.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclTomMath.decls"









#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all tcltest binaries libraries doc gendate gentommath_h install
.PHONY: install-binaries install-libraries install-tzdata install-msgs
.PHONY: install-doc install-private-headers test test-tcl runtest shell
.PHONY: gdb depend cleanhelp clean distclean packages install-packages
.PHONY: test-packages clean-packages distclean-packages genstubs html
.PHONY: html-tcl html-tk

# DO NOT DELETE THIS LINE -- make depend depends on it.

Changes to win/README.

89
90
91
92
93
94
95
96
97
98
99
-------------

This distribution contains an extensive test suite for Tcl.  Some of the
tests are timing dependent and will fail from time to time.  If a test is
failing consistently, please send us a bug report with as much detail as
you can manage to our tracker:

	https://core.tcl-lang.org/tcl/reportlist

In order to run the test suite, you build the "test" target using the
appropriate makefile for your compiler.







|



89
90
91
92
93
94
95
96
97
98
99
-------------

This distribution contains an extensive test suite for Tcl.  Some of the
tests are timing dependent and will fail from time to time.  If a test is
failing consistently, please send us a bug report with as much detail as
you can manage to our tracker:

	http://core.tcl.tk/tcl/reportlist

In order to run the test suite, you build the "test" target using the
appropriate makefile for your compiler.

Changes to win/cat.c.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
main(void)
{
    char buf[1024];
    int n;
    const char *err;

    while (1) {
	n = _read(0, buf, sizeof(buf));
	if (n <= 0) {
	    break;
	}
	_write(1, buf, n);
    }
    err = (sizeof(int) == 2) ? "stderr16" : "stderr32";
    _write(2, err, (unsigned int)strlen(err));

    return 0;
}







|



|


|



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
main(void)
{
    char buf[1024];
    int n;
    const char *err;

    while (1) {
	n = read(0, buf, sizeof(buf));
	if (n <= 0) {
	    break;
	}
        write(1, buf, n);
    }
    err = (sizeof(int) == 2) ? "stderr16" : "stderr32";
    write(2, err, strlen(err));

    return 0;
}

Changes to win/configure.

1
2
3
4
5
6
7
8
9
10
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for tcl 8.5.
#
# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##


|







1
2
3
4
5
6
7
8
9
10
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

# Maximum number of lines to put in a shell here document.
# This variable seems obsolete.  It should probably be removed, and
# only ac_max_sed_lines should be used.
: ${ac_max_here_lines=38}

# Identity of this package.
PACKAGE_NAME='tcl'
PACKAGE_TARNAME='tcl'
PACKAGE_VERSION='8.5'
PACKAGE_STRING='tcl 8.5'
PACKAGE_BUGREPORT=''

ac_unique_file="../generic/tcl.h"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>







|
|
|
|
|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

# Maximum number of lines to put in a shell here document.
# This variable seems obsolete.  It should probably be removed, and
# only ac_max_sed_lines should be used.
: ${ac_max_here_lines=38}

# Identity of this package.
PACKAGE_NAME=
PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=

ac_unique_file="../generic/tcl.h"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures tcl 8.5 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.







|







774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures this package to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
_ACEOF

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then
  case $ac_init_help in
     short | recursive ) echo "Configuration of tcl 8.5:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-threads        build with threads (default: off)
  --enable-shared         build and link with shared libraries (default: on)
  --enable-time64bit      force 64-bit time_t for 32-bit build (default: off)
  --enable-64bit          enable 64bit support (where applicable)
  --enable-wince          enable Win/CE support (where applicable)
  --enable-symbols        build with debugging symbols (default: off)
  --enable-embedded-manifest
                          embed manifest if possible (default: yes)

Optional Packages:







|
<
<







<







830
831
832
833
834
835
836
837


838
839
840
841
842
843
844

845
846
847
848
849
850
851
_ACEOF

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then



  cat <<\_ACEOF

Optional Features:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-threads        build with threads (default: off)
  --enable-shared         build and link with shared libraries (default: on)

  --enable-64bit          enable 64bit support (where applicable)
  --enable-wince          enable Win/CE support (where applicable)
  --enable-symbols        build with debugging symbols (default: off)
  --enable-embedded-manifest
                          embed manifest if possible (default: yes)

Optional Packages:
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
    cd $ac_popdir
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF
tcl configure 8.5
generated by GNU Autoconf 2.59

Copyright (C) 2003 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
fi
exec 5>config.log
cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by tcl $as_me 8.5, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  $ $0 $@

_ACEOF
{
cat <<_ASUNAME







<
<












|







957
958
959
960
961
962
963


964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
    cd $ac_popdir
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF



Copyright (C) 2003 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
fi
exec 5>config.log
cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  $ $0 $@

_ACEOF
{
cat <<_ASUNAME
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
















# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.4
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=4
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

TCL_REG_VERSION=1.3
TCL_REG_MAJOR_VERSION=1
TCL_REG_MINOR_VERSION=3
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then







<
<
<
<
<
<
<
<
<











|

|


|

|







1299
1300
1301
1302
1303
1304
1305









1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
















# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=3
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

TCL_REG_VERSION=1.2
TCL_REG_MAJOR_VERSION=1
TCL_REG_MINOR_VERSION=2
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ctype.h>
#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \







<







2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ctype.h>

#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040

3041
3042

3043
3044

3045
3046
3047
3048
3049
3050
3051
3052
3053
3054

#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
set x ${MAKE-make}
ac_make=`echo "" | sed 'y,:./+-,___p_,'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.make <<\_ACEOF
SHELL = /bin/sh
all:
	@echo '@@@%%%=$(MAKE)=@@@%%%'
_ACEOF
# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
case `${MAKE-make} -f conftest.make 2>/dev/null` in
  *@@@%%%=?*=@@@%%%*)

    eval ac_cv_prog_make_${ac_make}_set=yes;;
  *)

    eval ac_cv_prog_make_${ac_make}_set=no;;
esac

rm -f conftest.make
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
  echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
  SET_MAKE=
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  SET_MAKE="MAKE=${MAKE-make}"







<
|




<

|

|
|
<
>
|
<
>
|
<
>


|







3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017

3018
3019
3020
3021
3022

3023
3024

3025
3026

3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037

#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6

set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.make <<\_ACEOF

all:
	@echo 'ac_maketemp="$(MAKE)"'
_ACEOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`

if test -n "$ac_maketemp"; then
  eval ac_cv_prog_make_${ac_make}_set=yes

else
  eval ac_cv_prog_make_${ac_make}_set=no

fi
rm -f conftest.make
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
  echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
  SET_MAKE=
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
  SET_MAKE="MAKE=${MAKE-make}"
3136
3137
3138
3139
3140
3141
3142








3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182








































































3183
3184
3185
3186
3187
3188
3189
    # Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;








    if test "$tcl_ok" = "yes" ; then
	echo "$as_me:$LINENO: result: shared" >&5
echo "${ECHO_T}shared" >&6
	SHARED_BUILD=1
    else
	echo "$as_me:$LINENO: result: static" >&5
echo "${ECHO_T}static" >&6
	SHARED_BUILD=0

cat >>confdefs.h <<\_ACEOF
#define STATIC_BUILD 1
_ACEOF

    fi


#--------------------------------------------------------------------
# Check whether --enable-time64bit was given.
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking force of 64-bit time_t" >&5
echo $ECHO_N "checking force of 64-bit time_t... $ECHO_C" >&6
# Check whether --enable-time64bit or --disable-time64bit was given.
if test "${enable_time64bit+set}" = set; then
  enableval="$enable_time64bit"
  tcl_ok=$enableval
else
  tcl_ok=no
fi;
echo "$as_me:$LINENO: result: \"$tcl_ok\"" >&5
echo "${ECHO_T}\"$tcl_ok\"" >&6
if test "$tcl_ok" = "yes"; then
    CFLAGS="${CFLAGS} -D_USE_64BIT_TIME_T"
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------











































































    # Step 0: Enable 64 bit support?

    echo "$as_me:$LINENO: checking if 64bit support is requested" >&5
echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6







>
>
>
>
>
>
>
>
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149



















3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
    # Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	echo "$as_me:$LINENO: result: shared" >&5
echo "${ECHO_T}shared" >&6
	SHARED_BUILD=1
    else
	echo "$as_me:$LINENO: result: static" >&5
echo "${ECHO_T}static" >&6
	SHARED_BUILD=0

cat >>confdefs.h <<\_ACEOF
#define STATIC_BUILD 1
_ACEOF

    fi





















#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

# On IRIX 5.3, sys/types and inttypes.h are conflicting.









for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
		  inttypes.h stdint.h unistd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default

#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  eval "$as_ac_Header=yes"
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

eval "$as_ac_Header=no"
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
if test `eval echo '${'$as_ac_Header'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done




    # Step 0: Enable 64 bit support?

    echo "$as_me:$LINENO: checking if 64bit support is requested" >&5
echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
  CELIB_DIR=NO_CELIB
fi;
    echo "$as_me:$LINENO: result: $CELIB_DIR" >&5
echo "${ECHO_T}$CELIB_DIR" >&6

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""

cat >>confdefs.h <<\_ACEOF
#define MODULE_SCOPE extern
_ACEOF


    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CYGPATH+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6







<
<
<
<
<







3266
3267
3268
3269
3270
3271
3272





3273
3274
3275
3276
3277
3278
3279
  CELIB_DIR=NO_CELIB
fi;
    echo "$as_me:$LINENO: result: $CELIB_DIR" >&5
echo "${ECHO_T}$CELIB_DIR" >&6

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""






    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CYGPATH+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

	    #ifndef _WIN32
		#error cross-compiler
	    #endif

int
main ()
{








|







3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

	    #ifndef __WIN32__
		#error cross-compiler
	    #endif

int
main ()
{

3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		#ifdef _WIN32
		    #error win32
		#endif

int
main ()
{








|







3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

		#ifdef __WIN32__
		    #error win32
		#endif

int
main ()
{

3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492



3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509




3510


3511


3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
	fi
    fi

    echo "$as_me:$LINENO: checking compiler flags" >&5
echo $ECHO_N "checking compiler flags... $ECHO_C" >&6
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"
	MAKE_STUB_LIB="\${STLIB_LD} \$@"
	POST_MAKE_LIB="\${RANLIB} \$@"
	MAKE_EXE="\${CC} -o \$@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
	    runtime=



	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		{ { echo "$as_me:$LINENO: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&5
echo "$as_me: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&2;}
   { (exit 1); exit 1; }; }
	    fi

	    runtime=




	    # Add SHLIB_LD_LIBS to the Make rule, not here.





	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi
	# Link with gcc since ld does not link to default libs like
	# -luser32 and -lmsvcrt by default.
	SHLIB_LD='${CC} -shared'
	SHLIB_LD_LIBS='${LIBS}'
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.dll.a,\$@)"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.a"
	LIBFLAGSUFFIX="\${DBGX}"
	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall -Wdeclaration-after-statement -Wpointer-arith"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \$@"
	CC_EXENAME="-o \$@"








|




















>
>
>

















>
>
>
>

>
>

>
>



<
<
<
<
<
<



<
<






|







3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564






3565
3566
3567


3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
	fi
    fi

    echo "$as_me:$LINENO: checking compiler flags" >&5
echo $ECHO_N "checking compiler flags... $ECHO_C" >&6
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS=""
	LIBS="-lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"
	MAKE_STUB_LIB="\${STLIB_LD} \$@"
	POST_MAKE_LIB="\${RANLIB} \$@"
	MAKE_EXE="\${CC} -o \$@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
	    runtime=
	    MAKE_DLL="echo "
	    LIBSUFFIX="s\${DBGX}.a"
	    LIBFLAGSUFFIX="s\${DBGX}"
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		{ { echo "$as_me:$LINENO: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&5
echo "$as_me: error: ${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." >&2;}
   { (exit 1); exit 1; }; }
	    fi

	    runtime=
	    # Link with gcc since ld does not link to default libs like
	    # -luser32 and -lmsvcrt by default.
	    SHLIB_LD='${CC} -shared'
	    SHLIB_LD_LIBS='${LIBS}'
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \
	        -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\$@)"

	    LIBSUFFIX="\${DBGX}.a"
	    LIBFLAGSUFFIX="\${DBGX}"
	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi






	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"


	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \$@"
	CC_EXENAME="-o \$@"

3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632



3633
3634

3635
3636
3637
3638
3639
3640
3641


3642


3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657



3658





3659
3660
3661

3662
3663
3664

3665
3666




3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681























3682














































3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
sed 's/^/| /' conftest.$ac_ext >&5

tcl_win_64bit=no

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
		if test "$tcl_win_64bit" = "yes" ; then
		    do64bit=amd64
		    MACHINE="AMD64"
		    echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
	    runtime=-MT



	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"

	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"


	    EXESUFFIX="\${DBGX}.exe"


	    case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.lib"
	LIBFLAGSUFFIX="\${DBGX}"




	if test "$do64bit" != "no" ; then





	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build

		    ;;
		ia64)
		    MACHINE="IA64"

		    ;;
	    esac




	    echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
	fi

	LIBS="user32.lib advapi32.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then























	    RC="rc"














































	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE}"
	    LINKBIN="link"
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors







|
|
|










>
>
>


>






|
>
>

>
>








<



<
<

>
>
>

>
>
>
>
>



>



>


>
>
>
>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|







3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703


3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
sed 's/^/| /' conftest.$ac_ext >&5

tcl_win_64bit=no

fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
		if test "$tcl_win_64bit" = "yes" ; then
			do64bit=amd64
			MACHINE="AMD64"
			echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            echo "$as_me:$LINENO: result: using static flags" >&5
echo "${ECHO_T}using static flags" >&6
	    runtime=-MT
	    MAKE_DLL="echo "
	    LIBSUFFIX="s\${DBGX}.lib"
	    LIBFLAGSUFFIX="s\${DBGX}"
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    SHLIB_LD_LIBS=""
	else
	    # dynamic
            echo "$as_me:$LINENO: result: using shared flags" >&5
echo "${ECHO_T}using shared flags" >&6
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@"
	    LIBSUFFIX="\${DBGX}.lib"
	    LIBFLAGSUFFIX="\${DBGX}"
	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    SHLIB_LD_LIBS='${LIBS}'
	    case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi

	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"



	# This is a 2-stage check to make sure we have the 64-bit SDK
	# We have to know where the SDK is installed.
	# This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
	if test "$do64bit" != "no" ; then
	    if test "x${MSSDK}x" = "xx" ; then
		MSSDK="C:/Progra~1/Microsoft Platform SDK"
	    fi
	    MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
	    PATH64=""
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
		    ;;
		ia64)
		    MACHINE="IA64"
		    PATH64="${MSSDK}/Bin/Win64"
		    ;;
	    esac
	    if test ! -d "${PATH64}" ; then
		{ echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK" >&5
echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK" >&2;}
	    fi
	    echo "$as_me:$LINENO: result:    Using 64-bit $MACHINE mode" >&5
echo "${ECHO_T}   Using 64-bit $MACHINE mode" >&6
	fi

	LIBS="user32.lib advapi32.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.  TEA has the
	    # TEA_PATH_NOSPACE to avoid this issue.
	    # Check if _WIN64 is already recognized, and if so we don't
	    # need to modify CC.
	    echo "$as_me:$LINENO: checking whether _WIN64 is declared" >&5
echo $ECHO_N "checking whether _WIN64 is declared... $ECHO_C" >&6
if test "${ac_cv_have_decl__WIN64+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
#ifndef _WIN64
  char *p = (char *) _WIN64;
#endif

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_have_decl__WIN64=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_have_decl__WIN64=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_have_decl__WIN64" >&5
echo "${ECHO_T}$ac_cv_have_decl__WIN64" >&6
if test $ac_cv_have_decl__WIN64 = yes; then
  :
else
  CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \
			 -I\"${MSSDK}/Include/crt\" \
			 -I\"${MSSDK}/Include/crt/sys\""
fi

	    RC="\"${MSSDK}/bin/rc.exe\""
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
	    LINKBIN="\"${PATH64}/link.exe\""
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res







<







3932
3933
3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"

	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222

    # DL_LIBS is empty, but then we match the Unix version






# On IRIX 5.3, sys/types and inttypes.h are conflicting.









for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
		  inttypes.h stdint.h unistd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default

#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  eval "$as_ac_Header=yes"
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

eval "$as_ac_Header=no"
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
if test `eval echo '${'$as_ac_Header'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done


echo "$as_me:$LINENO: checking for intptr_t" >&5
echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6
if test "${ac_cv_type_intptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







4266
4267
4268
4269
4270
4271
4272








































































4273
4274
4275
4276
4277
4278
4279

    # DL_LIBS is empty, but then we match the Unix version














































































echo "$as_me:$LINENO: checking for intptr_t" >&5
echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6
if test "${ac_cv_type_intptr_t+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"

if test ${SHARED_BUILD} = 0 -o "$GCC" != "yes" ; then
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${DLLSUFFIX}.a\""
fi

eval "TCL_LIB_FLAG=\"-ltcl${VER}${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""







<
|
<
<
<







4771
4772
4773
4774
4775
4776
4777

4778



4779
4780
4781
4782
4783
4784
4785
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"


eval "TCL_LIB_FILE=${LIBPREFIX}tcl$VER${LIBSUFFIX}"




eval "TCL_LIB_FLAG=\"-ltcl${VER}${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892






                                        ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#







<







4931
4932
4933
4934
4935
4936
4937

4938
4939
4940
4941
4942
4943
4944






                                        ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

This file was extended by tcl $as_me 8.5, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@







|







5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

This file was extended by $as_me, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
$config_files

Report bugs to <[email protected]>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
tcl config.status 8.5
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=$srcdir







|







5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
$config_files

Report bugs to <[email protected]>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=$srcdir

Changes to win/configure.in.

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
#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tcl installation
# to configure the system for the local environment.

AC_INIT([tcl],[8.5])
AC_CONFIG_SRCDIR([../generic/tcl.h])
AC_PREREQ([2.59])

# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.4
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=4
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

TCL_REG_VERSION=1.3
TCL_REG_MAJOR_VERSION=1
TCL_REG_MINOR_VERSION=3
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then





<
|
|












|

|


|

|







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
#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tcl installation
# to configure the system for the local environment.


AC_INIT(../generic/tcl.h)
AC_PREREQ(2.59)

# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL=".19"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=3
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

TCL_REG_VERSION=1.2
TCL_REG_MAJOR_VERSION=1
TCL_REG_MINOR_VERSION=2
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
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
#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

SC_ENABLE_SHARED

#--------------------------------------------------------------------
# Check whether --enable-time64bit was given.
#--------------------------------------------------------------------

AC_MSG_CHECKING([force of 64-bit time_t])
AC_ARG_ENABLE(time64bit,
    AS_HELP_STRING([--enable-time64bit],
	[force 64-bit time_t for 32-bit build (default: off)]),
    [tcl_ok=$enableval], [tcl_ok=no])
AC_MSG_RESULT("$tcl_ok")
if test "$tcl_ok" = "yes"; then
    CFLAGS="${CFLAGS} -D_USE_64BIT_TIME_T"
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS







<
<
<
<
<
<
<
<
<
<
<
<
<
<







86
87
88
89
90
91
92














93
94
95
96
97
98
99
#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

SC_ENABLE_SHARED















#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

SC_CONFIG_CFLAGS
150
151
152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173

# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h,
    tcl_cv_findex_enums,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
]], [[

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;
]])],
    [tcl_cv_findex_enums=yes],
    [tcl_cv_findex_enums=no])
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
fi

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







|



|
>


|
|
|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h,
    tcl_cv_findex_enums,
AC_TRY_COMPILE([
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
],
[
  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;
],
        tcl_cv_findex_enums=yes,
        tcl_cv_findex_enums=no)
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
fi

#--------------------------------------------------------------------
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"

if test ${SHARED_BUILD} = 0 -o "$GCC" != "yes" ; then
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${DLLSUFFIX}.a\""
fi

eval "TCL_LIB_FLAG=\"-ltcl${VER}${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""







<
|
<
<
<







186
187
188
189
190
191
192

193



194
195
196
197
198
199
200
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"


eval "TCL_LIB_FILE=${LIBPREFIX}tcl$VER${LIBSUFFIX}"




eval "TCL_LIB_FLAG=\"-ltcl${VER}${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""
363
364
365
366
367
368
369
370
371
372
373
374
375
AC_SUBST(RC_OUT)
AC_SUBST(RC_TYPE)
AC_SUBST(RC_INCLUDE)
AC_SUBST(RC_DEFINE)
AC_SUBST(RC_DEFINES)
AC_SUBST(RES)

AC_CONFIG_FILES([Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf
dnl End:







|
<


|

345
346
347
348
349
350
351
352

353
354
355
356
AC_SUBST(RC_OUT)
AC_SUBST(RC_TYPE)
AC_SUBST(RC_INCLUDE)
AC_SUBST(RC_DEFINE)
AC_SUBST(RC_DEFINES)
AC_SUBST(RES)

AC_OUTPUT(Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest)


dnl Local Variables:
dnl mode: autoconf;
dnl End:

Changes to win/makefile.bc.

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
######################################################################

NAMEPREFIX	= tcl
STUBPREFIX	= $(NAMEPREFIX)stub
DOTVERSION	= 8.5
VERSION		= 85

DDEVERSION = 14
DDEDOTVERSION = 1.4

REGVERSION = 13
REGDOTVERSION = 1.3

BINROOT		= ..
!IF "$(NODEBUG)" == "1"
TMPDIRNAME	= Release
DBGX		=
SYMDEFINES	= -DNDEBUG
!ELSE







|
|

|
|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
######################################################################

NAMEPREFIX	= tcl
STUBPREFIX	= $(NAMEPREFIX)stub
DOTVERSION	= 8.5
VERSION		= 85

DDEVERSION = 13
DDEDOTVERSION = 1.3

REGVERSION = 12
REGDOTVERSION = 1.2

BINROOT		= ..
!IF "$(NODEBUG)" == "1"
TMPDIRNAME	= Release
DBGX		=
SYMDEFINES	= -DNDEBUG
!ELSE
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	$(TMPDIR)\tclWinPipe.obj \
	$(TMPDIR)\tclWinSock.obj \
	$(TMPDIR)\tclWinThrd.obj \
	$(TMPDIR)\tclWinTime.obj

TCLSTUBOBJS	= $(TMPDIR)\tclStubLib.obj

WIN_DIR		= $(ROOT)\win
GENERICDIR	= $(ROOT)\generic

TCL_INCLUDES	= -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TCL_DEFINES	= $(DEBUGDEFINES) $(THREADDEFINES) $(SYMDEFINES) \
			$(PROFDEFINES) $(OPTDEFINES) $(SIXFOURDEFINES) \
			-DTCL_CFGVAL_ENCODING=${CFG_ENCODING}

######################################################################
# Compiler flags
######################################################################







|


|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	$(TMPDIR)\tclWinPipe.obj \
	$(TMPDIR)\tclWinSock.obj \
	$(TMPDIR)\tclWinThrd.obj \
	$(TMPDIR)\tclWinTime.obj

TCLSTUBOBJS	= $(TMPDIR)\tclStubLib.obj

WINDIR		= $(ROOT)\win
GENERICDIR	= $(ROOT)\generic

TCL_INCLUDES	= -I"$(WINDIR)" -I"$(GENERICDIR)"
TCL_DEFINES	= $(DEBUGDEFINES) $(THREADDEFINES) $(SYMDEFINES) \
			$(PROFDEFINES) $(OPTDEFINES) $(SIXFOURDEFINES) \
			-DTCL_CFGVAL_ENCODING=${CFG_ENCODING}

######################################################################
# Compiler flags
######################################################################
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
		-out:$@ $(conlibsdll) $(TCLPLUGINLIB) $(TCLSHOBJS)

$(TCLTEST): $(TCLTESTOBJS) $(TCLLIB) $(TMPDIR)\$(NAMEPREFIX)sh.res
	$(link32) $(ldebug) -S:2400000 $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 @&&!
		$(TCLTESTOBJS), $@, -x, $(LNLIBS) $(TCLLIB),, $(TMPDIR)\$(NAMEPREFIX)sh.res
!

$(TCLPIPEDLL): $(WIN_DIR)\stub16.c
	$(cc32) $(CFLAGS) -o$(TMPDIR)\stub16.obj $(WIN_DIR)\stub16.c
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 \
		$(TMPDIR)\stub16.obj, $@, -x, $(LNLIBS),, $(TMPDIR)\$(NAMEPREFIX).res

$(TCLDDEDLL): $(TMPDIR)\tclWinDde.obj $(TCLSTUBLIB)
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \
		$(TMPDIR)\tclWinDde.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \
		$(TMPDIR)\$(NAMEPREFIX).res

$(TCLREGDLL): $(TMPDIR)\tclWinReg.obj $(TCLSTUBLIB)
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \
		$(TMPDIR)\tclWinReg.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \
		$(TMPDIR)\$(NAMEPREFIX).res

$(CAT32): $(WIN_DIR)\cat.c
	$(cc32) $(CONS_CFLAGS) -o$(TMPDIR)\cat.obj $?
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 \
		$(TMPDIR)\cat.obj, $@, -x, $(LNLIBS),,

install-binaries: $(TCLSH)
	$(MKDIR) "$(BIN_INSTALL_DIR)"
	$(MKDIR) "$(LIB_INSTALL_DIR)"







|
|













|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
		-out:$@ $(conlibsdll) $(TCLPLUGINLIB) $(TCLSHOBJS)

$(TCLTEST): $(TCLTESTOBJS) $(TCLLIB) $(TMPDIR)\$(NAMEPREFIX)sh.res
	$(link32) $(ldebug) -S:2400000 $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 @&&!
		$(TCLTESTOBJS), $@, -x, $(LNLIBS) $(TCLLIB),, $(TMPDIR)\$(NAMEPREFIX)sh.res
!

$(TCLPIPEDLL): $(WINDIR)\stub16.c
	$(cc32) $(CFLAGS) -o$(TMPDIR)\stub16.obj $(WINDIR)\stub16.c
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 \
		$(TMPDIR)\stub16.obj, $@, -x, $(LNLIBS),, $(TMPDIR)\$(NAMEPREFIX).res

$(TCLDDEDLL): $(TMPDIR)\tclWinDde.obj $(TCLSTUBLIB)
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \
		$(TMPDIR)\tclWinDde.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \
		$(TMPDIR)\$(NAMEPREFIX).res

$(TCLREGDLL): $(TMPDIR)\tclWinReg.obj $(TCLSTUBLIB)
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \
		$(TMPDIR)\tclWinReg.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \
		$(TMPDIR)\$(NAMEPREFIX).res

$(CAT32): $(WINDIR)\cat.c
	$(cc32) $(CONS_CFLAGS) -o$(TMPDIR)\cat.obj $?
	$(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 \
		$(TMPDIR)\cat.obj, $@, -x, $(LNLIBS),,

install-binaries: $(TCLSH)
	$(MKDIR) "$(BIN_INSTALL_DIR)"
	$(MKDIR) "$(LIB_INSTALL_DIR)"
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4"
	-@copy "$(ROOT)\library\opt\optparse.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
	-@copy "$(ROOT)\library\opt\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
	@echo Installing msgcat1.5
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	-@copy "$(ROOT)\library\msgcat\msgcat.tcl"   "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	-@copy "$(ROOT)\library\msgcat\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	@echo Installing tcltest2.5
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\tcltest2.5"
	-@copy "$(ROOT)\library\tcltest\tcltest.tcl"   "$(SCRIPT_INSTALL_DIR)\tcltest2.5"
	-@copy "$(ROOT)\library\tcltest\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.5"
	@echo Installing platform1.0
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\platform.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\shell.tcl"    "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
	@echo Installing $(TCLDDEDLLNAME)
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\dde1.3"







|
|
|
|







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4"
	-@copy "$(ROOT)\library\opt\optparse.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
	-@copy "$(ROOT)\library\opt\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
	@echo Installing msgcat1.5
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	-@copy "$(ROOT)\library\msgcat\msgcat.tcl"   "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	-@copy "$(ROOT)\library\msgcat\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.5"
	@echo Installing tcltest2.3
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
	-@copy "$(ROOT)\library\tcltest\tcltest.tcl"   "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
	-@copy "$(ROOT)\library\tcltest\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
	@echo Installing platform1.0
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\platform.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\shell.tcl"    "$(SCRIPT_INSTALL_DIR)\platform1.0"
	-@copy "$(ROOT)\library\platform\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
	@echo Installing $(TCLDDEDLLNAME)
	-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\dde1.3"
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
$(TCLRTF): $(MAN2TCL).exe $(TCLSH)
	cd $(TCLTOOLS)
	..\win\$(TCLSH) $(MAN2HELP) $(NAMEPREFIX) $(VERSION) $(ROOT)/doc ../../tk$(DOTVERSION)/doc

#
# Special case object file targets
#
$(TMPDIR)\tclWinInit.obj: $(WIN_DIR)\tclWinInit.c
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\testMain.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) -DTCL_TEST -o$(TMPDIR)\testMain.obj $?

$(TMPDIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclWinTest.obj: $(WIN_DIR)\tclWinTest.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
	$(cc32) $(TCL_CFLAGS) \
		-DCFG_INSTALL_EXEC_PREFIX=\"$(INSTALL_EXEC_PREFIX)\"	\
		-DCFG_INSTALL_PREFIX=\"$(INSTALL_PREFIX)\"		\
		-DCFG_RUNTIME_EXEC_PREFIX=\"$(RUNTIME_EXEC_PREFIX)\"	\
		-DCFG_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\"		\
	 -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclAppInit.obj : $(WIN_DIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

# The following objects should be built using the stub interfaces

# tclWinReg: Produces errors in ANSI mode
$(TMPDIR)\tclWinReg.obj : $(WIN_DIR)\tclWinReg.c
	$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $?

# tclWinDde: Produces errors in ANSI mode
$(TMPDIR)\tclWinDde.obj : $(WIN_DIR)\tclWinDde.c
	$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $?


# The following objects are part of the stub library and should not
# be built as DLL objects but none of the symbols should be exported

$(TMPDIR)\tclStubLib.obj : $(GENERICDIR)\tclStubLib.c







|


|








|










|





|



|







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
$(TCLRTF): $(MAN2TCL).exe $(TCLSH)
	cd $(TCLTOOLS)
	..\win\$(TCLSH) $(MAN2HELP) $(NAMEPREFIX) $(VERSION) $(ROOT)/doc ../../tk$(DOTVERSION)/doc

#
# Special case object file targets
#
$(TMPDIR)\tclWinInit.obj: $(WINDIR)\tclWinInit.c
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\testMain.obj: $(WINDIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) -DTCL_TEST -o$(TMPDIR)\testMain.obj $?

$(TMPDIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
	$(cc32) $(TCL_CFLAGS) \
		-DCFG_INSTALL_EXEC_PREFIX=\"$(INSTALL_EXEC_PREFIX)\"	\
		-DCFG_INSTALL_PREFIX=\"$(INSTALL_PREFIX)\"		\
		-DCFG_RUNTIME_EXEC_PREFIX=\"$(RUNTIME_EXEC_PREFIX)\"	\
		-DCFG_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\"		\
	 -o$(TMPDIR)\$@ $?

$(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?

# The following objects should be built using the stub interfaces

# tclWinReg: Produces errors in ANSI mode
$(TMPDIR)\tclWinReg.obj : $(WINDIR)\tclWinReg.c
	$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $?

# tclWinDde: Produces errors in ANSI mode
$(TMPDIR)\tclWinDde.obj : $(WINDIR)\tclWinDde.c
	$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $?


# The following objects are part of the stub library and should not
# be built as DLL objects but none of the symbols should be exported

$(TMPDIR)\tclStubLib.obj : $(GENERICDIR)\tclStubLib.c
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
$(GENERICDIR)\regfronts.c: $(GENERICDIR)\regguts.h
$(GENERICDIR)\regguts.h: $(GENERICDIR)\regcustom.h

#
# Implicit rules
#

{$(WIN_DIR)}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(GENERICDIR)}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(ROOT)\compat}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(WIN_DIR)}.rc{$(TMPDIR)}.res:
	$(rc32) $(INCLUDEPATH) -D$(USERDEFINES);$(SYSDEFINES) -fo$@ $<

clean:
	-@$(RM) $(OUTDIR)\*.exp
	-@$(RM) $(OUTDIR)\*.lib
	-@$(RM) $(OUTDIR)\*.dll
	-@$(RM) $(OUTDIR)\*.exe







|








|







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
$(GENERICDIR)\regfronts.c: $(GENERICDIR)\regguts.h
$(GENERICDIR)\regguts.h: $(GENERICDIR)\regcustom.h

#
# Implicit rules
#

{$(WINDIR)}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(GENERICDIR)}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(ROOT)\compat}.c{$(TMPDIR)}.obj:
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $<

{$(WINDIR)}.rc{$(TMPDIR)}.res:
	$(rc32) $(INCLUDEPATH) -D$(USERDEFINES);$(SYSDEFINES) -fo$@ $<

clean:
	-@$(RM) $(OUTDIR)\*.exp
	-@$(RM) $(OUTDIR)\*.lib
	-@$(RM) $(OUTDIR)\*.dll
	-@$(RM) $(OUTDIR)\*.exe

Changes to win/makefile.vc.

1

2
3
4
5
6
7
8
9
10
#------------------------------------------------------------- -*- makefile -*-

#
#	Microsoft Visual C++ makefile for building Tcl with nmake
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001-2005 ActiveState Corporation.

>

|







1
2
3
4
5
6
7
8
9
10
11
#------------------------------------------------------------- -*- makefile -*-
# makefile.vc --
#
#	Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001-2005 ActiveState Corporation.
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#		    files found in $(ROOT)\doc.
#
# 4)  Macros usable on the commandline:
#	INSTALLDIR=<path>
#		Sets where to install Tcl from the built binaries.
#		C:\Progra~1\Tcl is assumed when not specified.
#
#	OPTS=loimpact,msvcrt,static,staticpkg,symbols,threads,profile,unchecked,time64bit,none
#		Sets special options for the core.  The default is for none.
#		Any combination of the above may be used (comma separated).
#		'none' will over-ride everything to nothing.
#
#		loimpact = Adds a flag for how NT treats the heap to keep memory
#			   in use, low.  This is said to impact alloc performance.
#		msvcrt   = Affects the static option only to switch it from







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#		    files found in $(ROOT)\doc.
#
# 4)  Macros usable on the commandline:
#	INSTALLDIR=<path>
#		Sets where to install Tcl from the built binaries.
#		C:\Progra~1\Tcl is assumed when not specified.
#
#	OPTS=loimpact,msvcrt,static,staticpkg,symbols,threads,profile,unchecked,none
#		Sets special options for the core.  The default is for none.
#		Any combination of the above may be used (comma separated).
#		'none' will over-ride everything to nothing.
#
#		loimpact = Adds a flag for how NT treats the heap to keep memory
#			   in use, low.  This is said to impact alloc performance.
#		msvcrt   = Affects the static option only to switch it from
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#		thrdalloc = Use the thread allocator (shared global free pool).
#		thrdstorage = Use the generic thread storage support.
#		symbols =  Adds symbols for step debugging.
#		profile =  Adds profiling hooks.  Map file is assumed.
#		unchecked = Allows a symbols build to not use the debug
#			   enabled runtime (msvcrt.dll not msvcrtd.dll
#			   or libcmt.lib not libcmtd.lib).
#		time64bit = Forces a build using 64-bit time_t for 32-bit build
#			   (CRT library should support this).
#
#	STATS=compdbg,memdbg,none
#		Sets optional memory and bytecode compiler debugging code added
#		to the core.  The default is for none.  Any combination of the
#		above may be used (comma separated).  'none' will over-ride
#		everything to nothing.
#







<
<







90
91
92
93
94
95
96


97
98
99
100
101
102
103
#		thrdalloc = Use the thread allocator (shared global free pool).
#		thrdstorage = Use the generic thread storage support.
#		symbols =  Adds symbols for step debugging.
#		profile =  Adds profiling hooks.  Map file is assumed.
#		unchecked = Allows a symbols build to not use the debug
#			   enabled runtime (msvcrt.dll not msvcrtd.dll
#			   or libcmt.lib not libcmtd.lib).


#
#	STATS=compdbg,memdbg,none
#		Sets optional memory and bytecode compiler debugging code added
#		to the core.  The default is for none.  Any combination of the
#		above may be used (comma separated).  'none' will over-ride
#		everything to nothing.
#
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
PROJECT = tcl
!include "rules.vc"

STUBPREFIX      = $(PROJECT)stub
DOTVERSION      = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION         = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)

DDEDOTVERSION = 1.4
DDEVERSION = $(DDEDOTVERSION:.=)

REGDOTVERSION = 1.3
REGVERSION = $(REGDOTVERSION:.=)

BINROOT		= .
ROOT		= ..

TCLIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
TCLLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)







|


|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
PROJECT = tcl
!include "rules.vc"

STUBPREFIX      = $(PROJECT)stub
DOTVERSION      = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION         = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)

DDEDOTVERSION = 1.3
DDEVERSION = $(DDEDOTVERSION:.=)

REGDOTVERSION = 1.2
REGVERSION = $(REGDOTVERSION:.=)

BINROOT		= .
ROOT		= ..

TCLIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
TCLLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

### The following paths CANNOT have spaces in them.
COMPATDIR	= $(ROOT)\compat
DOCDIR		= $(ROOT)\doc
GENERICDIR	= $(ROOT)\generic
TOMMATHDIR	= $(ROOT)\libtommath
TOOLSDIR	= $(ROOT)\tools
WIN_DIR		= $(ROOT)\win

#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------

!if !$(DEBUG)
!if $(OPTIMIZING)







|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

### The following paths CANNOT have spaces in them.
COMPATDIR	= $(ROOT)\compat
DOCDIR		= $(ROOT)\doc
GENERICDIR	= $(ROOT)\generic
TOMMATHDIR	= $(ROOT)\libtommath
TOOLSDIR	= $(ROOT)\tools
WINDIR		= $(ROOT)\win

#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------

!if !$(DEBUG)
!if $(OPTIMIZING)
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
### Warnings are too many, can't support warnings into errors.
cdebug	= -Zi -Od $(DEBUGFLAGS)
!else
cdebug	= -Zi -WX $(DEBUGFLAGS)
!endif

### Declarations common to all compiler options
cwarn = $(WARNINGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\

!if $(MSVCRT)
!if $(DEBUG) && !$(UNCHECKED)
crt = -MDd
!else
crt = -MD
!endif
!else
!if $(DEBUG) && !$(UNCHECKED)
crt = -MTd
!else
crt = -MT
!endif
!endif

TCL_INCLUDES	= -I"$(WIN_DIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)"
TCL_DEFINES	= /DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\" /DTCL_TOMMATH /DMP_PREC=4 /Dinline=__inline
BASE_CFLAGS	= $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES)
CON_CFLAGS	= $(cflags) $(cdebug) $(crt) /DCONSOLE
TCL_CFLAGS	= $(BASE_CFLAGS) $(OPTDEFINES)
STUB_CFLAGS     = $(cflags) $(cdebug) $(OPTDEFINES)


#---------------------------------------------------------------------
# Link flags
#---------------------------------------------------------------------







|
















|
|

|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
### Warnings are too many, can't support warnings into errors.
cdebug	= -Zi -Od $(DEBUGFLAGS)
!else
cdebug	= -Zi -WX $(DEBUGFLAGS)
!endif

### Declarations common to all compiler options
cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\

!if $(MSVCRT)
!if $(DEBUG) && !$(UNCHECKED)
crt = -MDd
!else
crt = -MD
!endif
!else
!if $(DEBUG) && !$(UNCHECKED)
crt = -MTd
!else
crt = -MT
!endif
!endif

TCL_INCLUDES	= -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)"
TCL_DEFINES	= -DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\" -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline
BASE_CFLAGS	= $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES)
CON_CFLAGS	= $(cflags) $(cdebug) $(crt) -DCONSOLE
TCL_CFLAGS	= $(BASE_CFLAGS) $(OPTDEFINES)
STUB_CFLAGS     = $(cflags) $(cdebug) $(OPTDEFINES)


#---------------------------------------------------------------------
# Link flags
#---------------------------------------------------------------------
480
481
482
483
484
485
486








487
488
489
490
491
492
493
!if $(PROFILE)
lflags	= $(lflags) -profile
!endif

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif









!if $(LOIMPACT)
lflags	= $(lflags) -ws:aggressive
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console







>
>
>
>
>
>
>
>







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
!if $(PROFILE)
lflags	= $(lflags) -profile
!endif

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif

!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
### Align sections for PE size savings.
lflags	= $(lflags) -opt:nowin98
!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
### Align sections for speed in loading by choosing the virtual page size.
lflags	= $(lflags) -align:4096
!endif

!if $(LOIMPACT)
lflags	= $(lflags) -ws:aggressive
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
install:    install-binaries install-libraries install-docs

test: test-core
test-core: setup $(TCLTEST) dlls $(CAT32)
	set TCL_LIBRARY=$(ROOT:\=/)/library
!if "$(OS)" == "Windows_NT"  || "$(MSVCDIR)" == "IDE"
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		package ifneeded dde 1.4.3 [list load "$(TCLDDELIB:\=/)" Dde]
		package ifneeded registry 1.3.5 [list load "$(TCLREGLIB:\=/)" Registry]
<<
!else
	@echo Please wait while the tests are collected...
	$(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile << > tests.log
		package ifneeded dde 1.4.3 "$(TCLDDELIB:\=/)" dde]
		package ifneeded registry 1.3.5 "$(TCLREGLIB:\=/)" registry]
<<
	type tests.log | more
!endif

runtest: setup $(TCLTEST) dlls $(CAT32)
	set TCL_LIBRARY=$(ROOT:\=/)/library
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)







|
|




|
|







534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
install:    install-binaries install-libraries install-docs

test: test-core
test-core: setup $(TCLTEST) dlls $(CAT32)
	set TCL_LIBRARY=$(ROOT:\=/)/library
!if "$(OS)" == "Windows_NT"  || "$(MSVCDIR)" == "IDE"
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		package ifneeded dde 1.3.3 [list load "$(TCLDDELIB:\=/)" dde]
		package ifneeded registry 1.2.2 [list load "$(TCLREGLIB:\=/)" registry]
<<
!else
	@echo Please wait while the tests are collected...
	$(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile << > tests.log
		package ifneeded dde 1.3.3 "$(TCLDDELIB:\=/)" dde]
		package ifneeded registry 1.2.2 "$(TCLREGLIB:\=/)" registry]
<<
	type tests.log | more
!endif

runtest: setup $(TCLTEST) dlls $(CAT32)
	set TCL_LIBRARY=$(ROOT:\=/)/library
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

$(TCLLIB): $(TCLOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ @<<
$**
<<
!else
	$(link32) $(dlllflags) -base:@$(WIN_DIR)\coffbase.txt,tcl -out:$@ \
		$(baselibs) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
!endif

$(TCLSTUBLIB): $(TCLSTUBOBJS)
	$(lib32) -nologo $(LINKERFLAGS) -nodefaultlib -out:$@ $(TCLSTUBOBJS)

$(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $**
	$(_VC_MANIFEST_EMBED_EXE)

$(TCLTEST): $(TCLTESTOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $**
	$(_VC_MANIFEST_EMBED_EXE)

$(TCLPIPEDLL): $(WIN_DIR)\stub16.c
	$(cc32) $(CON_CFLAGS) -Fo$(TMP_DIR)\ $(WIN_DIR)\stub16.c
	$(link32) $(conlflags) -out:$@ $(TMP_DIR)\stub16.obj $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)

!if $(STATIC_BUILD)
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ $**
!else
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB)
	$(link32) $(dlllflags) -base:@$(WIN_DIR)\coffbase.txt,tcldde -out:$@ \
		$** $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
	-@del $*.lib
!endif

!if $(STATIC_BUILD)
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ $**
!else
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(TCLSTUBLIB)
	$(link32) $(dlllflags) -base:@$(WIN_DIR)\coffbase.txt,tclreg -out:$@ \
		$** $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
	-@del $*.lib
!endif

$(CAT32): $(WIN_DIR)\cat.c
	$(cc32) $(CON_CFLAGS) -Fo$(TMP_DIR)\ $?
	$(link32) $(conlflags) -out:$@ -stack:16384 $(TMP_DIR)\cat.obj \
		$(baselibs)
	$(_VC_MANIFEST_EMBED_EXE)

#---------------------------------------------------------------------
# Regenerate the stubs files.  [Development use only]







|


















|
|








|











|






|







568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

$(TCLLIB): $(TCLOBJS)
!if $(STATIC_BUILD)
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ @<<
$**
<<
!else
	$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcl -out:$@ \
		$(baselibs) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
!endif

$(TCLSTUBLIB): $(TCLSTUBOBJS)
	$(lib32) -nologo $(LINKERFLAGS) -nodefaultlib -out:$@ $(TCLSTUBOBJS)

$(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $**
	$(_VC_MANIFEST_EMBED_EXE)

$(TCLTEST): $(TCLTESTOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $**
	$(_VC_MANIFEST_EMBED_EXE)

$(TCLPIPEDLL): $(WINDIR)\stub16.c
	$(cc32) $(CON_CFLAGS) -Fo$(TMP_DIR)\ $(WINDIR)\stub16.c
	$(link32) $(conlflags) -out:$@ $(TMP_DIR)\stub16.obj $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)

!if $(STATIC_BUILD)
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ $**
!else
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB)
	$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcldde -out:$@ \
		$** $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
	-@del $*.lib
!endif

!if $(STATIC_BUILD)
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj
	$(lib32) -nologo $(LINKERFLAGS) -out:$@ $**
!else
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(TCLSTUBLIB)
	$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tclreg -out:$@ \
		$** $(baselibs)
	$(_VC_MANIFEST_EMBED_DLL)
	-@del $*.exp
	-@del $*.lib
!endif

$(CAT32): $(WINDIR)\cat.c
	$(cc32) $(CON_CFLAGS) -Fo$(TMP_DIR)\ $?
	$(link32) $(conlflags) -out:$@ -stack:16384 $(TMP_DIR)\cat.obj \
		$(baselibs)
	$(_VC_MANIFEST_EMBED_EXE)

#---------------------------------------------------------------------
# Regenerate the stubs files.  [Development use only]
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

#---------------------------------------------------------------------
# Build tclConfig.sh for the TEA build system.
#---------------------------------------------------------------------

tclConfig: $(OUT_DIR)\tclConfig.sh

$(OUT_DIR)\tclConfig.sh: $(WIN_DIR)\tclConfig.sh.in
	@echo Creating tclConfig.sh
        @nmakehlp -s << $** >$@
@TCL_DLL_FILE@       $(TCLLIBNAME)
@TCL_VERSION@        $(DOTVERSION)
@TCL_MAJOR_VERSION@  $(TCL_MAJOR_VERSION)
@TCL_MINOR_VERSION@  $(TCL_MINOR_VERSION)
@TCL_PATCH_LEVEL@    $(TCL_PATCH_LEVEL)







|







768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

#---------------------------------------------------------------------
# Build tclConfig.sh for the TEA build system.
#---------------------------------------------------------------------

tclConfig: $(OUT_DIR)\tclConfig.sh

$(OUT_DIR)\tclConfig.sh: $(WINDIR)\tclConfig.sh.in
	@echo Creating tclConfig.sh
        @nmakehlp -s << $** >$@
@TCL_DLL_FILE@       $(TCLLIBNAME)
@TCL_VERSION@        $(DOTVERSION)
@TCL_MAJOR_VERSION@  $(TCL_MAJOR_VERSION)
@TCL_MINOR_VERSION@  $(TCL_MINOR_VERSION)
@TCL_PATCH_LEVEL@    $(TCL_PATCH_LEVEL)
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
	--name-prefix=TclDate \
	$(GENERICDIR)/tclGetDate.y

#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------

$(TMP_DIR)\testMain.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) /DTCL_TEST \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclWinTest.obj: $(WIN_DIR)\tclWinTest.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
	$(cc32) /DBUILD_tcl $(TCL_CFLAGS) \
	/DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""	\
	/DCFG_RUNTIME_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""     \
	-Fo$@ $?

$(TMP_DIR)\tclAppInit.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

### The following objects should be built using the stub interfaces
### *ALL* extensions need to built with /DTCL_THREADS=1

$(TMP_DIR)\tclWinReg.obj: $(WIN_DIR)\tclWinReg.c
!if $(STATIC_BUILD)
	$(cc32) $(TCL_CFLAGS) /DTCL_THREADS=1 /DSTATIC_BUILD -Fo$@ $?
!else
	$(cc32) $(TCL_CFLAGS) /DTCL_THREADS=1 /DUSE_TCL_STUBS -Fo$@ $?
!endif


$(TMP_DIR)\tclWinDde.obj: $(WIN_DIR)\tclWinDde.c
!if $(STATIC_BUILD)
	$(cc32) $(TCL_CFLAGS) /DTCL_THREADS=1 /DSTATIC_BUILD -Fo$@ $?
!else
	$(cc32) $(TCL_CFLAGS) /DTCL_THREADS=1 /DUSE_TCL_STUBS -Fo$@ $?
!endif


### The following objects are part of the stub library and should not
### be built as DLL objects.  -Zl is used to avoid a dependency on any
### specific C run-time.

$(TMP_DIR)\tclStubLib.obj: $(GENERICDIR)\tclStubLib.c
	$(cc32) $(STUB_CFLAGS) -Zl /DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $?

$(TMP_DIR)\tclsh.exe.manifest: $(WIN_DIR)\tclsh.exe.manifest.in
	@nmakehlp -s << $** >$@
@MACHINE@	  $(MACHINE:IX86=X86)
@TCL_WIN_VERSION@  $(DOTVERSION).0.0
<<

#---------------------------------------------------------------------
# Generate the source dependencies.  Having dependency rules will
# improve incremental build accuracy without having to resort to a
# full rebuild just because some non-global header file like
# tclCompile.h was changed.  These rules aren't needed when building
# from scratch.
#---------------------------------------------------------------------

depend:
!if !exist($(TCLSH))
	@echo Build tclsh first!
!else
	$(TCLSH) $(TOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \
		-passthru:"/DBUILD_tcl $(TCL_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \
		$(COMPATDIR),$$(COMPATDIR) $(TOMMATHDIR),$$(TOMMATHDIR) $(WIN_DIR),$$(WIN_DIR) @<<
$(TCLOBJS)
<<
!endif

#---------------------------------------------------------------------
# Dependency rules
#---------------------------------------------------------------------







|
|
|








|



|
|
|
|
|
|
|
|
|
|
|


|

|



|

|

|

|



|

|

|








|

|


















|
|







843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
	--name-prefix=TclDate \
	$(GENERICDIR)/tclGetDate.y

#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------

$(TMP_DIR)\testMain.obj: $(WINDIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) -DTCL_TEST \
	    -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
	$(cc32) $(TCL_CFLAGS) -Fo$@ $?

$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
	$(cc32) -DBUILD_tcl $(TCL_CFLAGS) \
	-DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	-DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	-DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	-DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	-DCFG_INSTALL_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""	\
	-DCFG_RUNTIME_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	-DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	-DCFG_RUNTIME_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	-DCFG_RUNTIME_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	-DCFG_RUNTIME_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""     \
	-Fo$@ $?

$(TMP_DIR)\tclAppInit.obj: $(WINDIR)\tclAppInit.c
	$(cc32) $(TCL_CFLAGS) \
	    -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

### The following objects should be built using the stub interfaces
### *ALL* extensions need to built with -DTCL_THREADS=1

$(TMP_DIR)\tclWinReg.obj: $(WINDIR)\tclWinReg.c
!if $(STATIC_BUILD)
	$(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
!else
	$(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
!endif


$(TMP_DIR)\tclWinDde.obj: $(WINDIR)\tclWinDde.c
!if $(STATIC_BUILD)
	$(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
!else
	$(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
!endif


### The following objects are part of the stub library and should not
### be built as DLL objects.  -Zl is used to avoid a dependency on any
### specific C run-time.

$(TMP_DIR)\tclStubLib.obj: $(GENERICDIR)\tclStubLib.c
	$(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $?

$(TMP_DIR)\tclsh.exe.manifest: $(WINDIR)\tclsh.exe.manifest.in
	@nmakehlp -s << $** >$@
@MACHINE@	  $(MACHINE:IX86=X86)
@TCL_WIN_VERSION@  $(DOTVERSION).0.0
<<

#---------------------------------------------------------------------
# Generate the source dependencies.  Having dependency rules will
# improve incremental build accuracy without having to resort to a
# full rebuild just because some non-global header file like
# tclCompile.h was changed.  These rules aren't needed when building
# from scratch.
#---------------------------------------------------------------------

depend:
!if !exist($(TCLSH))
	@echo Build tclsh first!
!else
	$(TCLSH) $(TOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \
		-passthru:"-DBUILD_tcl $(TCL_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \
		$(COMPATDIR),$$(COMPATDIR) $(TOMMATHDIR),$$(TOMMATHDIR) $(WINDIR),$$(WINDIR) @<<
$(TCLOBJS)
<<
!endif

#---------------------------------------------------------------------
# Dependency rules
#---------------------------------------------------------------------
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
!message


#---------------------------------------------------------------------
# Implicit rules
#---------------------------------------------------------------------

{$(WIN_DIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) /DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(TOMMATHDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) /DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) /DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) /DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(WIN_DIR)}.rc{$(TMP_DIR)}.res:
	$(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
	    -d DEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
	    -d TCL_THREADS=$(TCL_THREADS) \
	    -d STATIC_BUILD=$(STATIC_BUILD) \
	    $<

$(TMP_DIR)\tclsh.res: $(TMP_DIR)\tclsh.exe.manifest







|
|




|




|




|



|







946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
!message


#---------------------------------------------------------------------
# Implicit rules
#---------------------------------------------------------------------

{$(WINDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(TOMMATHDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
	$(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(WINDIR)}.rc{$(TMP_DIR)}.res:
	$(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
	    -d DEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
	    -d TCL_THREADS=$(TCL_THREADS) \
	    -d STATIC_BUILD=$(STATIC_BUILD) \
	    $<

$(TMP_DIR)\tclsh.res: $(TMP_DIR)\tclsh.exe.manifest
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
	@if exist $(TCLDDELIB) del $(TCLDDELIB)
	@echo Removing $(TCLREGLIB) ...
	@if exist $(TCLREGLIB) del $(TCLREGLIB)

clean:
	@echo Cleaning $(TMP_DIR)\* ...
	@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
	@echo Cleaning $(WIN_DIR)\nmakehlp.obj ...
	@if exist $(WIN_DIR)\nmakehlp.obj del $(WIN_DIR)\nmakehlp.obj
	@echo Cleaning $(WIN_DIR)\nmakehlp.exe ...
	@if exist $(WIN_DIR)\nmakehlp.exe del $(WIN_DIR)\nmakehlp.exe
	@echo Cleaning $(WIN_DIR)\_junk.pch ...
	@if exist $(WIN_DIR)\_junk.pch del $(WIN_DIR)\_junk.pch
	@echo Cleaning $(WIN_DIR)\vercl.x ...
	@if exist $(WIN_DIR)\vercl.x del $(WIN_DIR)\vercl.x
	@echo Cleaning $(WIN_DIR)\vercl.i ...
	@if exist $(WIN_DIR)\vercl.i del $(WIN_DIR)\vercl.i
	@echo Cleaning $(WIN_DIR)\versions.vc ...
	@if exist $(WIN_DIR)\versions.vc del $(WIN_DIR)\versions.vc

realclean: hose

hose:
	@echo Hosing $(OUT_DIR)\* ...
	@if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)







|
|
|
|
|
|
|
|
|
|
|
|






1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
	@if exist $(TCLDDELIB) del $(TCLDDELIB)
	@echo Removing $(TCLREGLIB) ...
	@if exist $(TCLREGLIB) del $(TCLREGLIB)

clean:
	@echo Cleaning $(TMP_DIR)\* ...
	@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
	@echo Cleaning $(WINDIR)\nmakehlp.obj ...
	@if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
	@echo Cleaning $(WINDIR)\nmakehlp.exe ...
	@if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
	@echo Cleaning $(WINDIR)\_junk.pch ...
	@if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch
	@echo Cleaning $(WINDIR)\vercl.x ...
	@if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x
	@echo Cleaning $(WINDIR)\vercl.i ...
	@if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i
	@echo Cleaning $(WINDIR)\versions.vc ...
	@if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc

realclean: hose

hose:
	@echo Hosing $(OUT_DIR)\* ...
	@if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)

Changes to win/nmakehlp.c.

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
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#ifdef _MSC_VER



#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#endif
#include <stdio.h>
#include <math.h>

/*
 * This library is required for x64 builds with _some_ versions of MSVC
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define   snprintf	_snprintf
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static int LocateDependency(const char *keyfile);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;
    const char *s;

    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);








|
>
>
>


|

















>




|



<












|
|













|







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
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#define NO_SHLWAPI_GDI
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_REG
#include <shlwapi.h>
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#pragma comment (lib, "shlwapi.lib")
#include <stdio.h>
#include <math.h>

/*
 * This library is required for x64 builds with _some_ versions of MSVC
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#define   snprintf	_snprintf
#endif



/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);

static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(
    int argc,
    char *argv[])
{
    char msg[300];
    DWORD dwWritten;
    int chars;
    char *s;

    /*
     * Make sure children (cl.exe and link.exe) are kept quiet.
     */

    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return QualifyPath(argv[2]);

	case 'L':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		    "usage: %s -L keypath\n"
		    "Emit the fully qualified path of directory containing keypath\n"
		    "exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return LocateDependency(argv[2]);
	}
    }
    chars = snprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
	    "This is a little helper app to equalize shell differences between WinNT and\n"
	    "Win9x and get nmake.exe to accomplish its job.\n",
	    argv[0]);







<
<
<
<
<
<
<
<
<
<
<
<







168
169
170
171
172
173
174












175
176
177
178
179
180
181
		    "Emit the fully qualified path\n"
		    "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
		    &dwWritten, NULL);
		return 2;
	    }
	    return QualifyPath(argv[2]);












	}
    }
    chars = snprintf(msg, sizeof(msg) - 1,
	    "usage: %s -c|-f|-l|-Q|-s|-V ...\n"
	    "This is a little helper app to equalize shell differences between WinNT and\n"
	    "Win9x and get nmake.exe to accomplish its job.\n",
	    argv[0]);
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.







|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    char **options,
    int count)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];







|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    const char **options,
    int count)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.







|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match,
    int numdots)
{

    static char szBuffer[100];
    char *szResult = NULL;
    FILE *fp = fopen(filename, "rt");

    if (fp != NULL) {
	/*
	 * Read data until we see our match string.
	 */

	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit((unsigned char)*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
			    && !strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}


		*q = 0;
		szResult = p;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}







>









|









|








|
|



>
|
|







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match,
    int numdots)
{
    size_t cbBuffer = 100;
    static char szBuffer[100];
    char *szResult = NULL;
    FILE *fp = fopen(filename, "rt");

    if (fp != NULL) {
	/*
	 * Read data until we see our match string.
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit(*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
			    && (!strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}

		memcpy(szBuffer, p, q - p);
		szBuffer[q-p] = 0;
		szResult = szBuffer;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
    char * value;
} list_item_t;

/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
    list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;







|







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
    char * value;
} list_item_t;

/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
    list_item_t *itemPtr = malloc(sizeof(list_item_t));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;
607
608
609
610
611
612
613

614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{

    static char szBuffer[1024], szCopy[1024];

    list_item_t *substPtr = NULL;
    FILE *fp, *sp;

    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substutitions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
		unsigned char *ks, *ke, *vs, *ve;
		ks = (unsigned char*)szBuffer;
		while (ks && *ks && isspace(*ks)) ++ks;
		ke = ks;
		while (ke && *ke && !isspace(*ke)) ++ke;
		vs = ke;
		while (vs && *vs && isspace(*vs)) ++vs;
		ve = vs;
		while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
		*ke = 0, *ve = 0;
		list_insert(&substPtr, (char*)ks, (char*)vs);
	    }
	    fclose(sp);
	}

	/* debug: dump the list */
#ifndef NDEBUG
	{
	    int n = 0;
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
		fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
	    }
	}
#endif

	/*
	 * Run the substitutions over each line of the input
	 */

	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr) {
		char *m = strstr(szBuffer, p->key);
		if (m) {
		    char *cp, *op, *sp;
		    cp = szCopy;
		    op = szBuffer;
		    while (op != m) *cp++ = *op++;
		    sp = p->value;
		    while (sp && *sp) *cp++ = *sp++;
		    op += strlen(p->key);
		    while (*op) *cp++ = *op++;
		    *cp = 0;
		    memcpy(szBuffer, szCopy, sizeof(szCopy));
		}
	    }
	    printf("%s", szBuffer);
	}

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}

BOOL FileExists(LPCTSTR szPath)
{
#ifndef INVALID_FILE_ATTRIBUTES
    #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
    DWORD pathAttr = GetFileAttributes(szPath);
    return (pathAttr != INVALID_FILE_ATTRIBUTES &&
	    !(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
}


/*
 * QualifyPath --
 *
 *	This composes the current working directory with a provided path
 *	and returns the fully qualified and normalized path.
 *	Mostly needed to setup paths for testing.
 */

static int
QualifyPath(
    const char *szPath)
{
    char szCwd[MAX_PATH + 1];

    GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
    printf("%s\n", szCwd);
    return 0;
}

/*
 * Implements LocateDependency for a single directory. See that command
 * for an explanation.
 * Returns 0 if found after printing the directory.
 * Returns 1 if not found but no errors.
 * Returns 2 on any kind of error
 * Basically, these are used as exit codes for the process.
 */
static int LocateDependencyHelper(const char *dir, const char *keypath)
{
    HANDLE hSearch;
    char path[MAX_PATH+1];
    size_t dirlen;
    int keylen, ret;
    WIN32_FIND_DATA finfo;

    if (dir == NULL || keypath == NULL)
	return 2; /* Have no real error reporting mechanism into nmake */
    dirlen = strlen(dir);
    if ((dirlen + 3) > sizeof(path))
	return 2;
    strncpy(path, dir, dirlen);
    strncpy(path+dirlen, "\\*", 3);	/* Including terminating \0 */
    keylen = strlen(keypath);

#if 0 /* This function is not available in Visual C++ 6 */
    /*
     * Use numerics 0 -> FindExInfoStandard,
     * 1 -> FindExSearchLimitToDirectories,
     * as these are not defined in Visual C++ 6
     */
    hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
    hSearch = FindFirstFile(path, &finfo);
#endif
    if (hSearch == INVALID_HANDLE_VALUE)
	return 1; /* Not found */

    /* Loop through all subdirs checking if the keypath is under there */
    ret = 1; /* Assume not found */
    do {
	int sublen;
	/*
	 * We need to check it is a directory despite the
	 * FindExSearchLimitToDirectories in the above call. See SDK docs
	 */
	if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
	    continue;
	sublen = strlen(finfo.cFileName);
	if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
	    continue;		/* Path does not fit, assume not matched */
	strncpy(path+dirlen+1, finfo.cFileName, sublen);
	path[dirlen+1+sublen] = '\\';
	strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
	if (FileExists(path)) {
	    /* Found a match, print to stdout */
	    path[dirlen+1+sublen] = '\0';
	    QualifyPath(path);
	    ret = 0;
	    break;
	}
    } while (FindNextFile(hSearch, &finfo));
    FindClose(hSearch);
    return ret;
}

/*
 * LocateDependency --
 *
 *	Locates a dependency for a package.
 *        keypath - a relative path within the package directory
 *          that is used to confirm it is the correct directory.
 *	The search path for the package directory is currently only
 *      the parent and grandparent of the current working directory.
 *      If found, the command prints
 *         name_DIRPATH=<full path of located directory>
 *      and returns 0. If not found, does not print anything and returns 1.
 */
static int LocateDependency(const char *keypath)
{
    size_t i;
    int ret;
    static const char *paths[] = {"..", "..\\..", "..\\..\\.."};

    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
	ret = LocateDependencyHelper(paths[i], keypath);
	if (ret == 0)
	    return ret;
    }
    return ret;
}


/*
 * Local variables:
 *   mode: c
 *   c-basic-offset: 4
 *   fill-column: 78
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 */







>

>












|
















|













|
















|








<
<
<
<
<
<
<
<
<
<
<













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
<
<
<










600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678











679
680
681
682
683
684
685
686
687
688
689
690
691

















692



693








694












695














696




697







698

















699



700
701



702
703
704
705
706
707
708
709
710
711
 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{
    size_t cbBuffer = 1024;
    static char szBuffer[1024], szCopy[1024];
    char *szResult = NULL;
    list_item_t *substPtr = NULL;
    FILE *fp, *sp;

    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substutitions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, cbBuffer, sp) != NULL) {
		unsigned char *ks, *ke, *vs, *ve;
		ks = (unsigned char*)szBuffer;
		while (ks && *ks && isspace(*ks)) ++ks;
		ke = ks;
		while (ke && *ke && !isspace(*ke)) ++ke;
		vs = ke;
		while (vs && *vs && isspace(*vs)) ++vs;
		ve = vs;
		while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
		*ke = 0, *ve = 0;
		list_insert(&substPtr, (char*)ks, (char*)vs);
	    }
	    fclose(sp);
	}

	/* debug: dump the list */
#ifdef _DEBUG
	{
	    int n = 0;
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
		fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
	    }
	}
#endif

	/*
	 * Run the substitutions over each line of the input
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr) {
		char *m = strstr(szBuffer, p->key);
		if (m) {
		    char *cp, *op, *sp;
		    cp = szCopy;
		    op = szBuffer;
		    while (op != m) *cp++ = *op++;
		    sp = p->value;
		    while (sp && *sp) *cp++ = *sp++;
		    op += strlen(p->key);
		    while (*op) *cp++ = *op++;
		    *cp = 0;
		    memcpy(szBuffer, szCopy, sizeof(szCopy));
		}
	    }
	    printf(szBuffer);
	}

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}












/*
 * QualifyPath --
 *
 *	This composes the current working directory with a provided path
 *	and returns the fully qualified and normalized path.
 *	Mostly needed to setup paths for testing.
 */

static int
QualifyPath(
    const char *szPath)
{
    char szCwd[MAX_PATH + 1];

















    char szTmp[MAX_PATH + 1];



    char *p;








    GetCurrentDirectory(MAX_PATH, szCwd);












    while ((p = strchr(szPath, '/')) && *p)














	*p = '\\';




    PathCombine(szTmp, szCwd, szPath);







    PathCanonicalize(szCwd, szTmp);

















    printf("%s\n", szCwd);



    return 0;
}




/*
 * Local variables:
 *   mode: c
 *   c-basic-offset: 4
 *   fill-column: 78
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 */

Changes to win/rules.vc.

188
189
190
191
192
193
194













195
196
197
198
199
200
201
!endif
!endif

# Prevents "LNK1561: entry point must be defined" error compiling from VS-IDE:
!ifndef LINKER_TESTFLAGS
LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmhlp-out.txt
!endif














LINKERFLAGS     =

!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
LINKERFLAGS     =-ltcg
!endif








>
>
>
>
>
>
>
>
>
>
>
>
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
!endif
!endif

# Prevents "LNK1561: entry point must be defined" error compiling from VS-IDE:
!ifndef LINKER_TESTFLAGS
LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmhlp-out.txt
!endif

!if "$(MACHINE)" == "IX86"
### test for -align:4096, when align:512 will do.
!if [nmakehlp -l -opt:nowin98 $(LINKER_TESTFLAGS)]
!message *** Linker has 'Win98 alignment problem'
ALIGN98_HACK	= 1
!else
!message *** Linker does not have 'Win98 alignment problem'
ALIGN98_HACK	= 0
!endif
!else
ALIGN98_HACK	= 0
!endif

LINKERFLAGS     =

!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
LINKERFLAGS     =-ltcg
!endif

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
!message *** Doing staticpkg
TCL_USE_STATIC_PACKAGES	= 1
!else
TCL_USE_STATIC_PACKAGES	= 0
!endif
!if [nmakehlp -f $(OPTS) "threads"]
!message *** Doing threads
TCL_THREADS = 1
USE_THREAD_ALLOC = 1
!else
TCL_THREADS = 0
USE_THREAD_ALLOC = 0
!endif
!if [nmakehlp -f $(OPTS) "time64bit"]
!message *** Force 64-bit time_t
_USE_64BIT_TIME_T = 1
!endif
!if [nmakehlp -f $(OPTS) "symbols"]
!message *** Doing symbols
DEBUG		= 1
!else
DEBUG		= 0
!endif
!if [nmakehlp -f $(OPTS) "pdbs"]







|


|


<
<
<
<







249
250
251
252
253
254
255
256
257
258
259
260
261




262
263
264
265
266
267
268
!message *** Doing staticpkg
TCL_USE_STATIC_PACKAGES	= 1
!else
TCL_USE_STATIC_PACKAGES	= 0
!endif
!if [nmakehlp -f $(OPTS) "threads"]
!message *** Doing threads
TCL_THREADS	= 1
USE_THREAD_ALLOC = 1
!else
TCL_THREADS	= 0
USE_THREAD_ALLOC = 0
!endif




!if [nmakehlp -f $(OPTS) "symbols"]
!message *** Doing symbols
DEBUG		= 1
!else
DEBUG		= 0
!endif
!if [nmakehlp -f $(OPTS) "pdbs"]
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
!endif
!endif

#----------------------------------------------------------
# Set our defines now armed with our options.
#----------------------------------------------------------

OPTDEFINES	= /DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) /DSTDC_HEADERS /DUSE_NMAKE=1

!if $(TCL_MEM_DEBUG)
OPTDEFINES	= $(OPTDEFINES) /DTCL_MEM_DEBUG
!endif
!if $(TCL_COMPILE_DEBUG)
OPTDEFINES	= $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS
!endif
!if $(TCL_THREADS)
OPTDEFINES	= $(OPTDEFINES) /DTCL_THREADS=1
!if $(USE_THREAD_ALLOC)
OPTDEFINES	= $(OPTDEFINES) /DUSE_THREAD_ALLOC=1
!endif
!endif
!if $(STATIC_BUILD)
OPTDEFINES	= $(OPTDEFINES) /DSTATIC_BUILD
!endif
!if $(TCL_NO_DEPRECATED)
OPTDEFINES	= $(OPTDEFINES) /DTCL_NO_DEPRECATED
!endif

!if !$(DEBUG)
OPTDEFINES	= $(OPTDEFINES) /DNDEBUG
!if $(OPTIMIZING)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
!endif
!endif
!if $(PROFILE)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_PROFILED
!endif
!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
OPTDEFINES	= $(OPTDEFINES) /DNO_STRTOI64
!endif

!if "$(_USE_64BIT_TIME_T)" == "1"
OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T
!endif

#----------------------------------------------------------
# Locate the Tcl headers to build against
#----------------------------------------------------------

!if "$(PROJECT)" == "tcl"







|


|


|


|

|



|


|



|

|



|


|


|
<
<
<
<







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488




489
490
491
492
493
494
495
!endif
!endif

#----------------------------------------------------------
# Set our defines now armed with our options.
#----------------------------------------------------------

OPTDEFINES	= -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS

!if $(TCL_MEM_DEBUG)
OPTDEFINES	= $(OPTDEFINES) -DTCL_MEM_DEBUG
!endif
!if $(TCL_COMPILE_DEBUG)
OPTDEFINES	= $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
!endif
!if $(TCL_THREADS)
OPTDEFINES	= $(OPTDEFINES) -DTCL_THREADS=1
!if $(USE_THREAD_ALLOC)
OPTDEFINES	= $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
!endif
!endif
!if $(STATIC_BUILD)
OPTDEFINES	= $(OPTDEFINES) -DSTATIC_BUILD
!endif
!if $(TCL_NO_DEPRECATED)
OPTDEFINES	= $(OPTDEFINES) -DTCL_NO_DEPRECATED
!endif

!if !$(DEBUG)
OPTDEFINES	= $(OPTDEFINES) -DNDEBUG
!if $(OPTIMIZING)
OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
!endif
!endif
!if $(PROFILE)
OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_PROFILED
!endif
!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
OPTDEFINES	= $(OPTDEFINES) -DNO_STRTOI64




!endif

#----------------------------------------------------------
# Locate the Tcl headers to build against
#----------------------------------------------------------

!if "$(PROJECT)" == "tcl"
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
TCLSH		= "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH)) && $(TCL_THREADS)
TCLSH           = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe"
!endif
TCLSTUBLIB	= "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib"
COFFBASE	= \must\have\tcl\sources\to\build\this\target
TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"
!else
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH)) && $(TCL_THREADS)
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe"
!endif
TCLSTUBLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib"
COFFBASE	= "$(_TCLDIR)\win\coffbase.txt"
TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
!endif

!endif








|
|











|
|







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
TCLSH		= "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH)) && $(TCL_THREADS)
TCLSH           = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe"
!endif
TCLSTUBLIB	= "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= "$(_TCLDIR)\lib\tclreg12$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\lib\tcldde13$(SUFX:t=).lib"
COFFBASE	= \must\have\tcl\sources\to\build\this\target
TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"
!else
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
!if !exist($(TCLSH)) && $(TCL_THREADS)
TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe"
!endif
TCLSTUBLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg12$(SUFX:t=).lib"
TCLDDELIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde13$(SUFX:t=).lib"
COFFBASE	= "$(_TCLDIR)\win\coffbase.txt"
TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
!endif

!endif

Changes to win/tcl.dsp.

1551
1552
1553
1554
1555
1556
1557




1558
1559
1560
1561
1562
1563
SOURCE=.\tclWinTest.c
# End Source File
# Begin Source File

SOURCE=.\tclWinThrd.c
# End Source File
# Begin Source File





SOURCE=.\tclWinTime.c
# End Source File
# End Group
# End Target
# End Project







>
>
>
>






1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
SOURCE=.\tclWinTest.c
# End Source File
# Begin Source File

SOURCE=.\tclWinThrd.c
# End Source File
# Begin Source File

SOURCE=.\tclWinThrd.h
# End Source File
# Begin Source File

SOURCE=.\tclWinTime.c
# End Source File
# End Group
# End Target
# End Project

Changes to win/tcl.m4.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )







|

|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )







|

|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [







|







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Subst the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [
360
361
362
363
364
365
366








367
368
369
370
371
372
373
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	[  --enable-shared         build and link with shared libraries (default: on)],
	[tcl_ok=$enableval], [tcl_ok=yes])








    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])







>
>
>
>
>
>
>
>







360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	[  --enable-shared         build and link with shared libraries (default: on)],
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
    AC_MSG_CHECKING([for Windows/CE celib directory])
    AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR],
	    CELIB_DIR=$withval, CELIB_DIR=NO_CELIB)
    AC_MSG_RESULT([$CELIB_DIR])

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""
	AC_DEFINE(MODULE_SCOPE, [extern], [No need to mark inidividual symbols as hidden])

    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)

    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      AC_CACHE_CHECK(for cross-compile version of gcc,
	ac_cv_cross,
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #ifndef _WIN32
		#error cross-compiler
	    #endif
	]], [[]])],
	[ac_cv_cross=no],
	[ac_cv_cross=yes])
      )

      if test "$ac_cv_cross" = "yes"; then
	case "$do64bit" in
	    amd64|x64|yes)
		CC="x86_64-w64-mingw32-gcc"
		LD="x86_64-w64-mingw32-ld"







<













|
|


|
|
|







553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
    AC_MSG_CHECKING([for Windows/CE celib directory])
    AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR],
	    CELIB_DIR=$withval, CELIB_DIR=NO_CELIB)
    AC_MSG_RESULT([$CELIB_DIR])

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""


    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)

    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      AC_CACHE_CHECK(for cross-compile version of gcc,
	ac_cv_cross,
	AC_TRY_COMPILE([
	    #ifndef __WIN32__
		#error cross-compiler
	    #endif
	], [],
	ac_cv_cross=no,
	ac_cv_cross=yes)
      )

      if test "$ac_cv_cross" = "yes"; then
	case "$do64bit" in
	    amd64|x64|yes)
		CC="x86_64-w64-mingw32-gcc"
		LD="x86_64-w64-mingw32-ld"
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668



669
670
671
672
673
674
675
676
677
678
679
680
681




682


683


684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
    # set various compiler flags depending on whether we are using gcc or cl

    if test "${GCC}" = "yes" ; then
	extra_cflags="-pipe"
	extra_ldflags="-pipe -static-libgcc"
	AC_CACHE_CHECK(for mingw32 version of gcc,
	    ac_cv_win32,
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef _WIN32
		    #error win32
		#endif
	    ]], [[]])],
	    [ac_cv_win32=no],
	    [ac_cv_win32=yes])
	)
	if test "$ac_cv_win32" != "yes"; then
	    AC_MSG_ERROR([${CC} cannot produce win32 executables.])
	fi
    fi

    AC_MSG_CHECKING([compiler flags])
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@"
	POST_MAKE_LIB="\${RANLIB} \[$]@"
	MAKE_EXE="\${CC} -o \[$]@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=



	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		AC_MSG_ERROR([${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain.])
	    fi

	    runtime=




	    # Add SHLIB_LD_LIBS to the Make rule, not here.





	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi
	# Link with gcc since ld does not link to default libs like
	# -luser32 and -lmsvcrt by default.
	SHLIB_LD='${CC} -shared'
	SHLIB_LD_LIBS='${LIBS}'
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \
	    -Wl,--out-implib,\$(patsubst %.dll,lib%.dll.a,\[$]@)"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.a"
	LIBFLAGSUFFIX="\${DBGX}"
	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall -Wdeclaration-after-statement -Wpointer-arith"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \[$]@"
	CC_EXENAME="-o \[$]@"








|
|


|
|
|









|



















>
>
>













>
>
>
>

>
>

>
>



<
<
<
<
<
<



<
<






|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704






705
706
707


708
709
710
711
712
713
714
715
716
717
718
719
720
721
    # set various compiler flags depending on whether we are using gcc or cl

    if test "${GCC}" = "yes" ; then
	extra_cflags="-pipe"
	extra_ldflags="-pipe -static-libgcc"
	AC_CACHE_CHECK(for mingw32 version of gcc,
	    ac_cv_win32,
	    AC_TRY_COMPILE([
		#ifdef __WIN32__
		    #error win32
		#endif
	    ], [],
	    ac_cv_win32=no,
	    ac_cv_win32=yes)
	)
	if test "$ac_cv_win32" != "yes"; then
	    AC_MSG_ERROR([${CC} cannot produce win32 executables.])
	fi
    fi

    AC_MSG_CHECKING([compiler flags])
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS=""
	LIBS="-lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@"
	POST_MAKE_LIB="\${RANLIB} \[$]@"
	MAKE_EXE="\${CC} -o \[$]@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=
	    MAKE_DLL="echo "
	    LIBSUFFIX="s\${DBGX}.a"
	    LIBFLAGSUFFIX="s\${DBGX}"
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		AC_MSG_ERROR([${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain.])
	    fi

	    runtime=
	    # Link with gcc since ld does not link to default libs like
	    # -luser32 and -lmsvcrt by default.
	    SHLIB_LD='${CC} -shared'
	    SHLIB_LD_LIBS='${LIBS}'
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \
	        -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\[$]@)"

	    LIBSUFFIX="\${DBGX}.a"
	    LIBFLAGSUFFIX="\${DBGX}"
	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	fi






	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"


	SHLIB_SUFFIX=.dll

	EXTRA_CFLAGS="${extra_cflags}"

	CFLAGS_DEBUG=-g
	CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
	CFLAGS_WARNING="-Wall"
	LDFLAGS_DEBUG=
	LDFLAGS_OPTIMIZE=

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \[$]@"
	CC_EXENAME="-o \[$]@"

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758



759
760

761
762
763
764
765
766


767


768
769
770
771
772
773
774
775
776
777
778
779
780
781
782



783





784
785
786

787
788
789

790
791



792
793
794
795
796
797
798
799
800
801
802
803
804
805









806
807
808
809
810
811
812
813
814
815
816
817
818
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    ia64)
		MACHINE="IA64"
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    *)
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifndef _WIN64
			#error 32-bit
		    #endif
		]], [[]])],
		    [tcl_win_64bit=yes],
		    [tcl_win_64bit=no]
		)
		if test "$tcl_win_64bit" = "yes" ; then
		    do64bit=amd64
		    MACHINE="AMD64"
		    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=-MT



	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"

	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"


	    EXESUFFIX="\${DBGX}.exe"


	    case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi
	MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\[$]@"
	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"
	LIBSUFFIX="\${DBGX}.lib"
	LIBFLAGSUFFIX="\${DBGX}"




	if test "$do64bit" != "no" ; then





	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build

		    ;;
		ia64)
		    MACHINE="IA64"

		    ;;
	    esac



	    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
	fi

	LIBS="user32.lib advapi32.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then









	    RC="rc"
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE}"
	    LINKBIN="link"
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors







|



|
|
|


|
|
|








>
>
>


>





|
>
>

>
>








<



<
<

>
>
>

>
>
>
>
>



>



>


>
>
>














>
>
>
>
>
>
>
>
>
|



|
|







742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

794
795
796


797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    ia64)
		MACHINE="IA64"
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    *)
		AC_TRY_COMPILE([
		    #ifndef _WIN64
			#error 32-bit
		    #endif
		], [],
			tcl_win_64bit=yes,
			tcl_win_64bit=no
		)
		if test "$tcl_win_64bit" = "yes" ; then
			do64bit=amd64
			MACHINE="AMD64"
			AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    runtime=-MT
	    MAKE_DLL="echo "
	    LIBSUFFIX="s\${DBGX}.lib"
	    LIBFLAGSUFFIX="s\${DBGX}"
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s\${DBGX}.exe"
	    SHLIB_LD_LIBS=""
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\[$]@"
	    LIBSUFFIX="\${DBGX}.lib"
	    LIBFLAGSUFFIX="\${DBGX}"
	    EXESUFFIX="\${DBGX}.exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    SHLIB_LD_LIBS='${LIBS}'
	    case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
		    ;;
		*)
		    ;;
	    esac
	fi

	# DLLSUFFIX is separate because it is the building block for
	# users of tclConfig.sh that may build shared or static.
	DLLSUFFIX="\${DBGX}.dll"



	# This is a 2-stage check to make sure we have the 64-bit SDK
	# We have to know where the SDK is installed.
	# This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
	if test "$do64bit" != "no" ; then
	    if test "x${MSSDK}x" = "xx" ; then
		MSSDK="C:/Progra~1/Microsoft Platform SDK"
	    fi
	    MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
	    PATH64=""
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
		    ;;
		ia64)
		    MACHINE="IA64"
		    PATH64="${MSSDK}/Bin/Win64"
		    ;;
	    esac
	    if test ! -d "${PATH64}" ; then
		AC_MSG_WARN([Could not find 64-bit $MACHINE SDK])
	    fi
	    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
	fi

	LIBS="user32.lib advapi32.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.  TEA has the
	    # TEA_PATH_NOSPACE to avoid this issue.
	    # Check if _WIN64 is already recognized, and if so we don't
	    # need to modify CC.
	    AC_CHECK_DECL([_WIN64], [],
			  [CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \
			 -I\"${MSSDK}/Include/crt\" \
			 -I\"${MSSDK}/Include/crt/sys\""])
	    RC="\"${MSSDK}/bin/rc.exe\""
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
	    LINKBIN="\"${PATH64}/link.exe\""
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res







<







950
951
952
953
954
955
956

957
958
959
960
961
962
963
	    LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
	    LIBS_GUI="commctrl.lib commdlg.lib"
	else
	    LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	fi

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"

	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
    if test "$do64bit" != "no" ; then
	AC_DEFINE(TCL_CFG_DO64BIT)
    fi

    if test "${GCC}" = "yes" ; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	]])],
	    [tcl_cv_seh=yes],
	    [tcl_cv_seh=no],
	    [tcl_cv_seh=no])
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ]], [[
		EXCEPTION_DISPOSITION x;
	    ]])],
	    [tcl_cv_eh_disposition=yes],
	    [tcl_cv_eh_disposition=no])
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN
	    ]], [[
		CHAR c;
		SHORT s;
		LONG l;
	    ]])],
	    [tcl_cv_winnt_ignore_void=yes],
	    [tcl_cv_winnt_ignore_void=no])
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ]])],
	    [tcl_cv_cast_to_union=yes],
	    [tcl_cv_cast_to_union=no])
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi
    fi








|














|
|
|
|














|



|

|
|
|












|




|



|
|
|












|
>


|
|
|







993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
    if test "$do64bit" != "no" ; then
	AC_DEFINE(TCL_CFG_DO64BIT)
    fi

    if test "${GCC}" = "yes" ; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_TRY_RUN([
	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	],
	    tcl_cv_seh=yes,
	    tcl_cv_seh=no,
	    tcl_cv_seh=no)
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_TRY_COMPILE([
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ],[
		EXCEPTION_DISPOSITION x;
	    ],
		tcl_cv_eh_disposition=yes,
		tcl_cv_eh_disposition=no)
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_TRY_COMPILE([
		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN
	    ], [
		CHAR c;
		SHORT s;
		LONG l;
	    ],
        tcl_cv_winnt_ignore_void=yes,
        tcl_cv_winnt_ignore_void=no)
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi
    fi

1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
#		VC_MANIFEST_EMBED_EXE
#
#--------------------------------------------------------------------

AC_DEFUN([SC_EMBED_MANIFEST], [
    AC_MSG_CHECKING(whether to embed manifest)
    AC_ARG_ENABLE(embedded-manifest,
	AS_HELP_STRING([--enable-embedded-manifest],
		[embed manifest if possible (default: yes)]),
	[embed_ok=$enableval], [embed_ok=yes])

    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \







|







1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
#		VC_MANIFEST_EMBED_EXE
#
#--------------------------------------------------------------------

AC_DEFUN([SC_EMBED_MANIFEST], [
    AC_MSG_CHECKING(whether to embed manifest)
    AC_ARG_ENABLE(embedded-manifest,
	AC_HELP_STRING([--enable-embedded-manifest],
		[embed manifest if possible (default: yes)]),
	[embed_ok=$enableval], [embed_ok=yes])

    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \

Changes to win/tclAppInit.c.

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	extern Tcl_PackageInitProc Registry_Init;
	extern Tcl_PackageInitProc Dde_Init;
	extern Tcl_PackageInitProc Dde_SafeInit;

	if (Registry_Init(interp) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_StaticPackage(interp, "Registry", Registry_Init, NULL);

	if (Dde_Init(interp) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_StaticPackage(interp, "Dde", Dde_Init, Dde_SafeInit);
   }
#endif

    /*
     * Call the init functions for included packages. Each call should look
     * like this:
     *







|




|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	extern Tcl_PackageInitProc Registry_Init;
	extern Tcl_PackageInitProc Dde_Init;
	extern Tcl_PackageInitProc Dde_SafeInit;

	if (Registry_Init(interp) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_StaticPackage(interp, "registry", Registry_Init, NULL);

	if (Dde_Init(interp) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_StaticPackage(interp, "dde", Dde_Init, Dde_SafeInit);
   }
#endif

    /*
     * Call the init functions for included packages. Each call should look
     * like this:
     *

Changes to win/tclWin32Dll.c.

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
    MEMORY_BASIC_INFORMATION mbi;
				/* The information about the memory
				 * area in which the stack resides */

    if (!tsdPtr->stackBound
	|| ((UINT_PTR)&tsdPtr < (UINT_PTR)tsdPtr->stackBound)) {

	/*
	 * Either we haven't determined the stack bound in this thread,
	 * or else we've overflowed the bound that we previously
	 * determined.  We need to find a new stack bound from
	 * Windows.
	 */

	GetSystemInfo(&si);







|







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
    MEMORY_BASIC_INFORMATION mbi;
				/* The information about the memory
				 * area in which the stack resides */

    if (!tsdPtr->stackBound
	|| ((UINT_PTR)&tsdPtr < (UINT_PTR)tsdPtr->stackBound)) {

	/* 
	 * Either we haven't determined the stack bound in this thread,
	 * or else we've overflowed the bound that we previously
	 * determined.  We need to find a new stack bound from
	 * Windows.
	 */

	GetSystemInfo(&si);

Changes to win/tclWinChan.c.

963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
    }

    channel = NULL;

    switch (FileGetType(handle)) {
    case FILE_TYPE_SERIAL:
	/*
	 * Natively named serial ports "com1-9", "\\\\.\\comXX" are
	 * already done with the code above.
	 * Here we handle all other serial port names.
	 *
	 * Reopen channel for OVERLAPPED operation. Normally this shouldn't
	 * fail, because the channel exists.
	 */








|







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
    }

    channel = NULL;

    switch (FileGetType(handle)) {
    case FILE_TYPE_SERIAL:
	/*
	 * Natively named serial ports "com1-9", "\\\\.\\comXX" are 
	 * already done with the code above.
	 * Here we handle all other serial port names.
	 *
	 * Reopen channel for OVERLAPPED operation. Normally this shouldn't
	 * fail, because the channel exists.
	 */

1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

    infoPtr->nextPtr = NULL;
    infoPtr->validMask = permissions;
    infoPtr->watchMask = 0;
    infoPtr->flags = appendMode;
    infoPtr->handle = handle;
    infoPtr->dirty = 0;
    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName,
	    (ClientData) infoPtr, permissions);

    /*
     * Files have default translation of AUTO and ^Z eof char, which means
     * that a ^Z will be accepted as EOF when reading.







|







1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

    infoPtr->nextPtr = NULL;
    infoPtr->validMask = permissions;
    infoPtr->watchMask = 0;
    infoPtr->flags = appendMode;
    infoPtr->handle = handle;
    infoPtr->dirty = 0;
    sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName,
	    (ClientData) infoPtr, permissions);

    /*
     * Files have default translation of AUTO and ^Z eof char, which means
     * that a ^Z will be accepted as EOF when reading.
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

 /*
 *----------------------------------------------------------------------
 *
 * NativeIsComPort --
 *
 *	Determines if a path refers to a Windows serial port.
 *	A simple and efficient solution is to use a "name hint" to detect
 *      COM ports by their filename instead of resorting to a syscall
 *	to detect serialness after the fact.
 *	The following patterns cover common serial port names:
 *	    COM[1-9]:?
 *	    //./COM[0-9]+
 *	    \\.\COM[0-9]+
 *
 * Results:







|
|







1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

 /*
 *----------------------------------------------------------------------
 *
 * NativeIsComPort --
 *
 *	Determines if a path refers to a Windows serial port.
 *	A simple and efficient solution is to use a "name hint" to detect 
 *      COM ports by their filename instead of resorting to a syscall 
 *	to detect serialness after the fact.
 *	The following patterns cover common serial port names:
 *	    COM[1-9]:?
 *	    //./COM[0-9]+
 *	    \\.\COM[0-9]+
 *
 * Results:
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
	const WCHAR *p = (const WCHAR *) nativePath;
	int i, len = wcslen(p);

	/*
	 * 1. Look for com[1-9]:?
	 */

	if ( (len >= 4) && (len <= 5)
		&& (_wcsnicmp(p, L"com", 3) == 0) ) {
	    /*
	    * The 4th character must be a digit 1..9 optionally followed by a ":"
	    */

	    if ( (p[3] < L'1') || (p[3] > L'9') ) {
		return 0;
	    }
	    if ( (len == 5) && (p[4] != L':') ) {
		return 0;
	    }
	    return 1;
	}

	/*
	 * 2. Look for //./com[0-9]+ or \\.\com[0-9]+
	 */

	if ( (len >= 8) && (
		   (_wcsnicmp(p, L"//./com", 7) == 0)
		|| (_wcsnicmp(p, L"\\\\.\\com", 7) == 0) ) )
	{
	    /*
	    * Charaters 8..end must be a digits 0..9
	    */








|


















|







1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
	const WCHAR *p = (const WCHAR *) nativePath;
	int i, len = wcslen(p);

	/*
	 * 1. Look for com[1-9]:?
	 */

	if ( (len >= 4) && (len <= 5) 
		&& (_wcsnicmp(p, L"com", 3) == 0) ) {
	    /*
	    * The 4th character must be a digit 1..9 optionally followed by a ":"
	    */

	    if ( (p[3] < L'1') || (p[3] > L'9') ) {
		return 0;
	    }
	    if ( (len == 5) && (p[4] != L':') ) {
		return 0;
	    }
	    return 1;
	}

	/*
	 * 2. Look for //./com[0-9]+ or \\.\com[0-9]+
	 */

	if ( (len >= 8) && ( 
		   (_wcsnicmp(p, L"//./com", 7) == 0)
		|| (_wcsnicmp(p, L"\\\\.\\com", 7) == 0) ) )
	{
	    /*
	    * Charaters 8..end must be a digits 0..9
	    */

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
	const char *p = (const char *) nativePath;
	int   i, len = strlen(p);

	/*
	 * 1. Look for com[1-9]:?
	 */

	if ( (len >= 4) && (len <= 5)
		&& (strnicmp(p, "com", 3) == 0) ) {
	    /*
	    * The 4th character must be a digit 1..9 optionally followed by a ":"
	    */

	    if ( (p[3] < '1') || (p[3] > '9') ) {
		return 0;
	    }
	    if ( (len == 5) && (p[4] != ':') ) {
		return 0;
	    }
	    return 1;
	}

	/*
	 * 2. Look for //./com[0-9]+ or \\.\com[0-9]+
	 */

	if ( (len >= 8) && (
		   (strnicmp(p, "//./com", 7) == 0)
		|| (strnicmp(p, "\\\\.\\com", 7) == 0) ) )
	{
	    /*
	    * Charaters 8..end must be a digits 0..9
	    */








|


















|







1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
	const char *p = (const char *) nativePath;
	int   i, len = strlen(p);

	/*
	 * 1. Look for com[1-9]:?
	 */

	if ( (len >= 4) && (len <= 5) 
		&& (strnicmp(p, "com", 3) == 0) ) {
	    /*
	    * The 4th character must be a digit 1..9 optionally followed by a ":"
	    */

	    if ( (p[3] < '1') || (p[3] > '9') ) {
		return 0;
	    }
	    if ( (len == 5) && (p[4] != ':') ) {
		return 0;
	    }
	    return 1;
	}

	/*
	 * 2. Look for //./com[0-9]+ or \\.\com[0-9]+
	 */

	if ( (len >= 8) && ( 
		   (strnicmp(p, "//./com", 7) == 0)
		|| (strnicmp(p, "\\\\.\\com", 7) == 0) ) )
	{
	    /*
	    * Charaters 8..end must be a digits 0..9
	    */

Changes to win/tclWinConsole.c.

1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371

    /*
     * Use the pointer for the name of the result channel. This keeps the
     * channel names unique, since some may share handles (stdin/stdout/stderr
     * for instance).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName,
	    (ClientData) infoPtr, permissions);

    if (permissions & TCL_READABLE) {
	/*
	 * Make sure the console input buffer is ready for only character







|







1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371

    /*
     * Use the pointer for the name of the result channel. This keeps the
     * channel names unique, since some may share handles (stdin/stdout/stderr
     * for instance).
     */

    sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName,
	    (ClientData) infoPtr, permissions);

    if (permissions & TCL_READABLE) {
	/*
	 * Make sure the console input buffer is ready for only character

Changes to win/tclWinDde.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
 * tclWinDde.c --
 *
 *	This file provides functions that implement the "send" command,
 *	allowing commands to be passed from interpreter to interpreter.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"
#include <dde.h>
#include <ddeml.h>
#include <tchar.h>





#if !defined(NDEBUG)

    /* test POKE server Implemented for debug mode only */
#   undef CBF_FAIL_POKES
#   define CBF_FAIL_POKES 0
#endif

/*
 * The following structure is used to keep track of the interpreters
 * registered by this process.
 */

typedef struct RegisteredInterp {
    struct RegisteredInterp *nextPtr;
				/* The next interp this application knows
				 * about. */
    WCHAR *name;		/* Interpreter's name (malloc-ed). */
    Tcl_Obj *handlerPtr;	/* The server handler command */
    Tcl_Interp *interp;		/* The interpreter attached to this name. */
} RegisteredInterp;

/*
 * Used to keep track of conversations.
 */

typedef struct Conversation {
    struct Conversation *nextPtr;
				/* The next conversation in the list. */
    RegisteredInterp *riPtr;	/* The info we know about the conversation. */
    HCONV hConv;		/* The DDE handle for this conversation. */
    Tcl_Obj *returnPackagePtr;	/* The result package for this conversation. */
} Conversation;

typedef struct {
    Tcl_Interp *interp;
    int result;
    ATOM service;
    ATOM topic;
    HWND hwnd;
} DdeEnumServices;

typedef struct {
    Conversation *currentConversations;
				/* A list of conversations currently being
				 * processed. */
    RegisteredInterp *interpListPtr;
				/* List of all interpreters registered in the
				 * current process. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following variables cannot be placed in thread-local storage. The Mutex
 * ddeMutex guards access to the ddeInstance.
 */

static HSZ ddeServiceGlobal = 0;
static DWORD ddeInstance;	/* The application instance handle given to us
				 * by DdeInitialize. */
static int ddeIsServer = 0;

#define TCL_DDE_VERSION		"1.4.3"
#define TCL_DDE_PACKAGE_NAME	"dde"
#define TCL_DDE_SERVICE_NAME	L"TclEval"
#define TCL_DDE_EXECUTE_RESULT	L"$TCLEVAL$EXECUTE$RESULT"

#define DDE_FLAG_ASYNC 1
#define DDE_FLAG_BINARY 2
#define DDE_FLAG_FORCE 4

TCL_DECLARE_MUTEX(ddeMutex)

/*
 * Forward declarations for functions defined later in this file.
 */

static LRESULT CALLBACK	DdeClientWindowProc(HWND hwnd, UINT uMsg,
			    WPARAM wParam, LPARAM lParam);
static int		DdeCreateClient(DdeEnumServices *es);
static BOOL CALLBACK	DdeEnumWindowsCallback(HWND hwndTarget,
			    LPARAM lParam);
static void		DdeExitProc(void *clientData);
static int		DdeGetServicesList(Tcl_Interp *interp,
			    const WCHAR *serviceName, const WCHAR *topicName);
static HDDEDATA CALLBACK DdeServerProc(UINT uType, UINT uFmt, HCONV hConv,
			    HSZ ddeTopic, HSZ ddeItem, HDDEDATA hData,
			    DWORD dwData1, DWORD dwData2);
static LRESULT		DdeServicesOnAck(HWND hwnd, WPARAM wParam,
			    LPARAM lParam);
static void		DeleteProc(void *clientData);
static Tcl_Obj *	ExecuteRemoteObject(RegisteredInterp *riPtr,
			    Tcl_Obj *ddeObjectPtr);
static int		MakeDdeConnection(Tcl_Interp *interp,
			    const WCHAR *name, HCONV *ddeConvPtr);
static void		SetDdeError(Tcl_Interp *interp);
static int		DdeObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

#if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#endif

static unsigned char *
getByteArrayFromObj(
	Tcl_Obj *objPtr,
	size_t *lengthPtr
) {
    int length;

    unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, &length);
#if TCL_MAJOR_VERSION > 8
    if (sizeof(TCL_HASH_TYPE) > sizeof(int)) {
	/* 64-bit and TIP #494 situation: */
	 *lengthPtr = *(TCL_HASH_TYPE *) objPtr->internalRep.twoPtrValue.ptr1;
    } else
#endif
	/* 32-bit or without TIP #494 */
    *lengthPtr = (size_t) (unsigned) length;
    return result;
}

#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT int		Dde_Init(Tcl_Interp *interp);
DLLEXPORT int		Dde_SafeInit(Tcl_Interp *interp);
#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Dde_Init --
 *
 *	This function initializes the dde command.












<
<
<
<

|
|
|

>
>
>
>
|
>
|
|
|
<










|
















|







|



















<

|
|













|


|

|





|



|

|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<







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
120



121
122
123
124
125
126
127
/*
 * tclWinDde.c --
 *
 *	This file provides functions that implement the "send" command,
 *	allowing commands to be passed from interpreter to interpreter.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */





#include "tclInt.h"
#include "tclPort.h"
#include <dde.h>
#include <ddeml.h>

/*
 * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the Dde_Init
 * declaration is in the source file itself, which is only accessed when we
 * are building a library. DO NOT MOVE BEFORE ANY #include LINES. ONLY USE
 * EXTERN TO INDICATE EXPORTED FUNCTIONS FROM NOW ON.
 */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT


/*
 * The following structure is used to keep track of the interpreters
 * registered by this process.
 */

typedef struct RegisteredInterp {
    struct RegisteredInterp *nextPtr;
				/* The next interp this application knows
				 * about. */
    char *name;			/* Interpreter's name (malloc-ed). */
    Tcl_Obj *handlerPtr;	/* The server handler command */
    Tcl_Interp *interp;		/* The interpreter attached to this name. */
} RegisteredInterp;

/*
 * Used to keep track of conversations.
 */

typedef struct Conversation {
    struct Conversation *nextPtr;
				/* The next conversation in the list. */
    RegisteredInterp *riPtr;	/* The info we know about the conversation. */
    HCONV hConv;		/* The DDE handle for this conversation. */
    Tcl_Obj *returnPackagePtr;	/* The result package for this conversation. */
} Conversation;

typedef struct DdeEnumServices {
    Tcl_Interp *interp;
    int result;
    ATOM service;
    ATOM topic;
    HWND hwnd;
} DdeEnumServices;

typedef struct ThreadSpecificData {
    Conversation *currentConversations;
				/* A list of conversations currently being
				 * processed. */
    RegisteredInterp *interpListPtr;
				/* List of all interpreters registered in the
				 * current process. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * The following variables cannot be placed in thread-local storage. The Mutex
 * ddeMutex guards access to the ddeInstance.
 */

static HSZ ddeServiceGlobal = 0;
static DWORD ddeInstance;	/* The application instance handle given to us
				 * by DdeInitialize. */
static int ddeIsServer = 0;


#define TCL_DDE_PACKAGE_NAME	"dde"
#define TCL_DDE_SERVICE_NAME	"TclEval"
#define TCL_DDE_EXECUTE_RESULT	"$TCLEVAL$EXECUTE$RESULT"

#define DDE_FLAG_ASYNC 1
#define DDE_FLAG_BINARY 2
#define DDE_FLAG_FORCE 4

TCL_DECLARE_MUTEX(ddeMutex)

/*
 * Forward declarations for functions defined later in this file.
 */

static LRESULT CALLBACK	DdeClientWindowProc(HWND hwnd, UINT uMsg,
			    WPARAM wParam, LPARAM lParam);
static int		DdeCreateClient(struct DdeEnumServices *es);
static BOOL CALLBACK	DdeEnumWindowsCallback(HWND hwndTarget,
			    LPARAM lParam);
static void		DdeExitProc(ClientData clientData);
static int		DdeGetServicesList(Tcl_Interp *interp,
			    const char *serviceName, const char *topicName);
static HDDEDATA CALLBACK DdeServerProc(UINT uType, UINT uFmt, HCONV hConv,
			    HSZ ddeTopic, HSZ ddeItem, HDDEDATA hData,
			    DWORD dwData1, DWORD dwData2);
static LRESULT		DdeServicesOnAck(HWND hwnd, WPARAM wParam,
			    LPARAM lParam);
static void		DeleteProc(ClientData clientData);
static Tcl_Obj *	ExecuteRemoteObject(RegisteredInterp *riPtr,
			    Tcl_Obj *ddeObjectPtr);
static int		MakeDdeConnection(Tcl_Interp *interp,
			    const char *name, HCONV *ddeConvPtr);
static void		SetDdeError(Tcl_Interp *interp);
static int		DdeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

































EXTERN int		Dde_Init(Tcl_Interp *interp);
EXTERN int		Dde_SafeInit(Tcl_Interp *interp);




/*
 *----------------------------------------------------------------------
 *
 * Dde_Init --
 *
 *	This function initializes the dde command.
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
 *----------------------------------------------------------------------
 */

int
Dde_Init(
    Tcl_Interp *interp)
{
    if (!Tcl_InitStubs(interp, "8.5", 0)) {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, NULL, NULL);
    Tcl_CreateExitHandler(DdeExitProc, NULL);
    return Tcl_PkgProvideEx(interp, TCL_DDE_PACKAGE_NAME, TCL_DDE_VERSION, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Dde_SafeInit --
 *







|





|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
 *----------------------------------------------------------------------
 */

int
Dde_Init(
    Tcl_Interp *interp)
{
    if (!Tcl_InitStubs(interp, "8.1", 0)) {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, NULL, NULL);
    Tcl_CreateExitHandler(DdeExitProc, NULL);
    return Tcl_PkgProvide(interp, TCL_DDE_PACKAGE_NAME, "1.3.3");
}

/*
 *----------------------------------------------------------------------
 *
 * Dde_SafeInit --
 *
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
     * Make sure that the DDE server is there. This is done only once, add an
     * exit handler tear it down.
     */

    if (ddeInstance == 0) {
	Tcl_MutexLock(&ddeMutex);
	if (ddeInstance == 0) {
	    if (DdeInitializeW(&ddeInstance, (PFNCALLBACK)(void *)DdeServerProc,
		    CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS
		    | CBF_FAIL_POKES, 0) != DMLERR_NO_ERROR) {
		ddeInstance = 0;
	    }
	}
	Tcl_MutexUnlock(&ddeMutex);
    }
    if ((ddeServiceGlobal == 0) && (nameFound != 0)) {
	Tcl_MutexLock(&ddeMutex);
	if ((ddeServiceGlobal == 0) && (nameFound != 0)) {
	    ddeIsServer = 1;
	    Tcl_CreateExitHandler(DdeExitProc, NULL);
	    ddeServiceGlobal = DdeCreateStringHandleW(ddeInstance,
		    TCL_DDE_SERVICE_NAME, CP_WINUNICODE);
	    DdeNameService(ddeInstance, ddeServiceGlobal, 0L, DNS_REGISTER);
	} else {
	    ddeIsServer = 0;
	}
	Tcl_MutexUnlock(&ddeMutex);
    }
}







|












|
|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
     * Make sure that the DDE server is there. This is done only once, add an
     * exit handler tear it down.
     */

    if (ddeInstance == 0) {
	Tcl_MutexLock(&ddeMutex);
	if (ddeInstance == 0) {
	    if (DdeInitialize(&ddeInstance, (PFNCALLBACK) DdeServerProc,
		    CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS
		    | CBF_FAIL_POKES, 0) != DMLERR_NO_ERROR) {
		ddeInstance = 0;
	    }
	}
	Tcl_MutexUnlock(&ddeMutex);
    }
    if ((ddeServiceGlobal == 0) && (nameFound != 0)) {
	Tcl_MutexLock(&ddeMutex);
	if ((ddeServiceGlobal == 0) && (nameFound != 0)) {
	    ddeIsServer = 1;
	    Tcl_CreateExitHandler(DdeExitProc, NULL);
	    ddeServiceGlobal = DdeCreateStringHandle(ddeInstance,
		    TCL_DDE_SERVICE_NAME, 0);
	    DdeNameService(ddeInstance, ddeServiceGlobal, 0L, DNS_REGISTER);
	} else {
	    ddeIsServer = 0;
	}
	Tcl_MutexUnlock(&ddeMutex);
    }
}
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
 *	"send" command is created in the application's interpreter. The
 *	registration will be removed automatically if the interpreter is
 *	deleted or the "send" command is removed.
 *
 *----------------------------------------------------------------------
 */

static const WCHAR *
DdeSetServerName(
    Tcl_Interp *interp,
    const WCHAR *name, /* The name that will be used to refer to the
				 * interpreter in later "send" commands. Must
				 * be globally unique. */
    int flags,		/* DDE_FLAG_FORCE or 0 */
    Tcl_Obj *handlerPtr)	/* Name of the optional proc/command to handle
				 * incoming Dde eval's */
{
    int suffix, offset;
    RegisteredInterp *riPtr, *prevPtr;
    Tcl_DString dString;
    const WCHAR *actualName;
    Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;
    int n, srvCount = 0, lastSuffix, r = TCL_OK;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * See if the application is already registered; if so, remove its current
     * name from the registry. The deletion of the command will take care of







|


|









|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
 *	"send" command is created in the application's interpreter. The
 *	registration will be removed automatically if the interpreter is
 *	deleted or the "send" command is removed.
 *
 *----------------------------------------------------------------------
 */

static const char *
DdeSetServerName(
    Tcl_Interp *interp,
    const char *name, /* The name that will be used to refer to the
				 * interpreter in later "send" commands. Must
				 * be globally unique. */
    int flags,		/* DDE_FLAG_FORCE or 0 */
    Tcl_Obj *handlerPtr)	/* Name of the optional proc/command to handle
				 * incoming Dde eval's */
{
    int suffix, offset;
    RegisteredInterp *riPtr, *prevPtr;
    Tcl_DString dString;
    const char *actualName;
    Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;
    int n, srvCount = 0, lastSuffix, r = TCL_OK;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * See if the application is already registered; if so, remove its current
     * name from the registry. The deletion of the command will take care of
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421


422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

    if (name == NULL) {
	/*
	 * The name was NULL, so the caller is asking for the name of the
	 * current interp, but it doesn't have a name.
	 */

	return L"";
    }

    /*
     * Get the list of currently registered Tcl interpreters by calling the
     * internal implementation of the 'dde services' command.
     */

    Tcl_DStringInit(&dString);
    actualName = name;

    if (!(flags & DDE_FLAG_FORCE)) {
	r = DdeGetServicesList(interp, TCL_DDE_SERVICE_NAME, NULL);
	if (r == TCL_OK) {
	    srvListPtr = Tcl_GetObjResult(interp);
	}
	if (r == TCL_OK) {
	    r = Tcl_ListObjGetElements(interp, srvListPtr, &srvCount,
		    &srvPtrPtr);
	}
	if (r != TCL_OK) {
	    Tcl_DStringInit(&dString);
	    OutputDebugStringW(Tcl_UtfToWCharDString(Tcl_GetString(Tcl_GetObjResult(interp)), -1, &dString));
	    Tcl_DStringFree(&dString);
	    return NULL;
	}

	/*
	 * Pick a name to use for the application. Use "name" if it's not
	 * already in use. Otherwise add a suffix such as " #2", trying larger
	 * and larger numbers until we eventually find one that is unique.
	 */

	offset = lastSuffix = 0;
	suffix = 1;

	while (suffix != lastSuffix) {
	    lastSuffix = suffix;
	    if (suffix > 1) {
		if (suffix == 2) {
		    Tcl_DStringAppend(&dString, (char *)name, wcslen(name) * sizeof(WCHAR));
		    Tcl_DStringAppend(&dString, (char *)L" #", 2 * sizeof(WCHAR));
		    offset = Tcl_DStringLength(&dString);
		    Tcl_DStringSetLength(&dString, offset + sizeof(WCHAR) * TCL_INTEGER_SPACE);
		    actualName = (WCHAR *) Tcl_DStringValue(&dString);
		}
		_snwprintf((WCHAR *) (Tcl_DStringValue(&dString) + offset),
			TCL_INTEGER_SPACE, L"%d", suffix);
	    }

	    /*
	     * See if the name is already in use, if so increment suffix.
	     */

	    for (n = 0; n < srvCount; ++n) {
		Tcl_Obj* namePtr;
		Tcl_DString ds;

		Tcl_ListObjIndex(interp, srvPtrPtr[n], 1, &namePtr);
		Tcl_DStringInit(&ds);
		Tcl_UtfToWCharDString(Tcl_GetString(namePtr), -1, &ds);
		if (wcscmp(actualName, (WCHAR *)Tcl_DStringValue(&ds)) == 0) {
		    suffix++;
		    Tcl_DStringFree(&ds);
		    break;
		}
		Tcl_DStringFree(&ds);
	    }
	}


    }

    /*
     * We have found a unique name. Now add it to the registry.
     */

    riPtr = (RegisteredInterp *) Tcl_Alloc(sizeof(RegisteredInterp));
    riPtr->interp = interp;
    riPtr->name = (WCHAR *) Tcl_Alloc((wcslen(actualName) + 1) * sizeof(WCHAR));
    riPtr->nextPtr = tsdPtr->interpListPtr;
    riPtr->handlerPtr = handlerPtr;
    if (riPtr->handlerPtr != NULL) {
	Tcl_IncrRefCount(riPtr->handlerPtr);
    }
    tsdPtr->interpListPtr = riPtr;
    wcscpy(riPtr->name, actualName);

    if (Tcl_IsSafe(interp)) {
	Tcl_ExposeCommand(interp, "dde", "dde");
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd,
	    riPtr, DeleteProc);
    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    Tcl_DStringFree(&dString);

    /*
     * Re-initialize with the new name.







|




















<
|
<
















|
|

|
|

|
<








<


<
|
<

<


<


>
>






|

|






|






|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

338

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369

370
371

372

373

374
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

    if (name == NULL) {
	/*
	 * The name was NULL, so the caller is asking for the name of the
	 * current interp, but it doesn't have a name.
	 */

	return "";
    }

    /*
     * Get the list of currently registered Tcl interpreters by calling the
     * internal implementation of the 'dde services' command.
     */

    Tcl_DStringInit(&dString);
    actualName = name;

    if (!(flags & DDE_FLAG_FORCE)) {
	r = DdeGetServicesList(interp, TCL_DDE_SERVICE_NAME, NULL);
	if (r == TCL_OK) {
	    srvListPtr = Tcl_GetObjResult(interp);
	}
	if (r == TCL_OK) {
	    r = Tcl_ListObjGetElements(interp, srvListPtr, &srvCount,
		    &srvPtrPtr);
	}
	if (r != TCL_OK) {

	    OutputDebugString(Tcl_GetStringResult(interp));

	    return NULL;
	}

	/*
	 * Pick a name to use for the application. Use "name" if it's not
	 * already in use. Otherwise add a suffix such as " #2", trying larger
	 * and larger numbers until we eventually find one that is unique.
	 */

	offset = lastSuffix = 0;
	suffix = 1;

	while (suffix != lastSuffix) {
	    lastSuffix = suffix;
	    if (suffix > 1) {
		if (suffix == 2) {
		    Tcl_DStringAppend(&dString, name, -1);
		    Tcl_DStringAppend(&dString, " #", 2);
		    offset = Tcl_DStringLength(&dString);
		    Tcl_DStringSetLength(&dString, offset + TCL_INTEGER_SPACE);
		    actualName = Tcl_DStringValue(&dString);
		}
		sprintf(Tcl_DStringValue(&dString) + offset, "%d", suffix);

	    }

	    /*
	     * See if the name is already in use, if so increment suffix.
	     */

	    for (n = 0; n < srvCount; ++n) {
		Tcl_Obj* namePtr;


		Tcl_ListObjIndex(interp, srvPtrPtr[n], 1, &namePtr);

		if (strcmp(actualName, Tcl_GetString(namePtr)) == 0) {

		    suffix++;

		    break;
		}

	    }
	}
	Tcl_DStringSetLength(&dString,
		offset + (int)strlen(Tcl_DStringValue(&dString)+offset));
    }

    /*
     * We have found a unique name. Now add it to the registry.
     */

    riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp));
    riPtr->interp = interp;
    riPtr->name = ckalloc((unsigned int) strlen(actualName) + 1);
    riPtr->nextPtr = tsdPtr->interpListPtr;
    riPtr->handlerPtr = handlerPtr;
    if (riPtr->handlerPtr != NULL) {
	Tcl_IncrRefCount(riPtr->handlerPtr);
    }
    tsdPtr->interpListPtr = riPtr;
    strcpy(riPtr->name, actualName);

    if (Tcl_IsSafe(interp)) {
	Tcl_ExposeCommand(interp, "dde", "dde");
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd,
	    (ClientData) riPtr, DeleteProc);
    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    Tcl_DStringFree(&dString);

    /*
     * Re-initialize with the new name.
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
 *	The interpreter given by riPtr is unregistered.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteProc(
    void *clientData)	/* The interp we are deleting. */

{
    RegisteredInterp *riPtr = (RegisteredInterp *) clientData;
    RegisteredInterp *searchPtr, *prevPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL;
	    (searchPtr != NULL) && (searchPtr != riPtr);
	    prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) {
	/*
	 * Empty loop body.
	 */
    }

    if (searchPtr != NULL) {
	if (prevPtr == NULL) {
	    tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;
	} else {
	    prevPtr->nextPtr = searchPtr->nextPtr;
	}
    }
    Tcl_Free((char *) riPtr->name);
    if (riPtr->handlerPtr) {
	Tcl_DecrRefCount(riPtr->handlerPtr);
    }
    Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
}

/*







|
>




















|







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
 *	The interpreter given by riPtr is unregistered.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteProc(
    ClientData clientData)	/* The interp we are deleting passed as
				 * ClientData. */
{
    RegisteredInterp *riPtr = (RegisteredInterp *) clientData;
    RegisteredInterp *searchPtr, *prevPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL;
	    (searchPtr != NULL) && (searchPtr != riPtr);
	    prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) {
	/*
	 * Empty loop body.
	 */
    }

    if (searchPtr != NULL) {
	if (prevPtr == NULL) {
	    tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;
	} else {
	    prevPtr->nextPtr = searchPtr->nextPtr;
	}
    }
    ckfree(riPtr->name);
    if (riPtr->handlerPtr) {
	Tcl_DecrRefCount(riPtr->handlerPtr);
    }
    Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
}

/*
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
ExecuteRemoteObject(
    RegisteredInterp *riPtr,	    /* Info about this server. */
    Tcl_Obj *ddeObjectPtr)	    /* The object to execute. */
{
    Tcl_Obj *returnPackagePtr;
    int result = TCL_OK;

    if ((riPtr->handlerPtr == NULL) && Tcl_IsSafe(riPtr->interp)) {
	Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj("permission denied: "
		"a handler procedure must be defined for use in a safe "
		"interp", -1));
	Tcl_SetErrorCode(riPtr->interp, "TCL", "DDE", "SECURITY_CHECK", NULL);
	result = TCL_ERROR;
    }

    if (riPtr->handlerPtr != NULL) {
	/*
	 * Add the dde request data to the handler proc list.
	 */







|



<







520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
ExecuteRemoteObject(
    RegisteredInterp *riPtr,	    /* Info about this server. */
    Tcl_Obj *ddeObjectPtr)	    /* The object to execute. */
{
    Tcl_Obj *returnPackagePtr;
    int result = TCL_OK;

    if (riPtr->handlerPtr == NULL && Tcl_IsSafe(riPtr->interp)) {
	Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj("permission denied: "
		"a handler procedure must be defined for use in a safe "
		"interp", -1));

	result = TCL_ERROR;
    }

    if (riPtr->handlerPtr != NULL) {
	/*
	 * Add the dde request data to the handler proc list.
	 */
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
				 * performing. */
    UINT uFmt,			/* The format that data is sent or received */
    HCONV hConv,		/* The conversation associated with the
				 * current transaction. */
    HSZ ddeTopic, HSZ ddeItem,	/* String handles. Transaction-type
				 * dependent. */
    HDDEDATA hData,		/* DDE data. Transaction-type dependent. */
    DWORD unused1, DWORD unused2)
				/* Transaction-dependent data. */
{
    Tcl_DString dString;
    size_t len;
    DWORD dlen;
    WCHAR *utilString;
    Tcl_Obj *ddeObjectPtr;
    HDDEDATA ddeReturn = NULL;
    RegisteredInterp *riPtr;
    Conversation *convPtr, *prevConvPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    (void)unused1;
    (void)unused2;

    switch(uType) {
    case XTYP_CONNECT:
	/*
	 * Dde is trying to initialize a conversation with us. Check and make
	 * sure we have a valid topic.
	 */

	len = DdeQueryStringW(ddeInstance, ddeTopic, NULL, 0, CP_WINUNICODE);
	Tcl_DStringInit(&dString);
	Tcl_DStringSetLength(&dString, (len + 1) * sizeof(WCHAR) - 1);
	utilString = (WCHAR *) Tcl_DStringValue(&dString);
	DdeQueryStringW(ddeInstance, ddeTopic, utilString, (DWORD) len + 1,
		CP_WINUNICODE);

	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (_wcsicmp(utilString, riPtr->name) == 0) {
		Tcl_DStringFree(&dString);
		return (HDDEDATA) TRUE;
	    }
	}

	Tcl_DStringFree(&dString);
	return (HDDEDATA) FALSE;

    case XTYP_CONNECT_CONFIRM:
	/*
	 * Dde has decided that we can connect, so it gives us a conversation
	 * handle. We need to keep track of it so we know which execution
	 * result to return in an XTYP_REQUEST.
	 */

	len = DdeQueryStringW(ddeInstance, ddeTopic, NULL, 0, CP_WINUNICODE);
	Tcl_DStringInit(&dString);
	Tcl_DStringSetLength(&dString,  (len + 1) * sizeof(WCHAR) - 1);
	utilString = (WCHAR *) Tcl_DStringValue(&dString);
	DdeQueryStringW(ddeInstance, ddeTopic, utilString, (DWORD) len + 1,
		CP_WINUNICODE);
	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (_wcsicmp(riPtr->name, utilString) == 0) {
		convPtr = (Conversation *) Tcl_Alloc(sizeof(Conversation));
		convPtr->nextPtr = tsdPtr->currentConversations;
		convPtr->returnPackagePtr = NULL;
		convPtr->hConv = hConv;
		convPtr->riPtr = riPtr;
		tsdPtr->currentConversations = convPtr;
		break;
	    }







|



|

|





<
<








|

|
|
|
|



|















|

|
|
|
|


|
|







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615


616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
				 * performing. */
    UINT uFmt,			/* The format that data is sent or received */
    HCONV hConv,		/* The conversation associated with the
				 * current transaction. */
    HSZ ddeTopic, HSZ ddeItem,	/* String handles. Transaction-type
				 * dependent. */
    HDDEDATA hData,		/* DDE data. Transaction-type dependent. */
    DWORD dwData1, DWORD dwData2)
				/* Transaction-dependent data. */
{
    Tcl_DString dString;
    int len;
    DWORD dlen;
    char *utilString;
    Tcl_Obj *ddeObjectPtr;
    HDDEDATA ddeReturn = NULL;
    RegisteredInterp *riPtr;
    Conversation *convPtr, *prevConvPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);



    switch(uType) {
    case XTYP_CONNECT:
	/*
	 * Dde is trying to initialize a conversation with us. Check and make
	 * sure we have a valid topic.
	 */

	len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0);
	Tcl_DStringInit(&dString);
	Tcl_DStringSetLength(&dString, len);
	utilString = Tcl_DStringValue(&dString);
	DdeQueryString(ddeInstance, ddeTopic, utilString, (DWORD) len + 1,
		CP_WINANSI);

	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (stricmp(utilString, riPtr->name) == 0) {
		Tcl_DStringFree(&dString);
		return (HDDEDATA) TRUE;
	    }
	}

	Tcl_DStringFree(&dString);
	return (HDDEDATA) FALSE;

    case XTYP_CONNECT_CONFIRM:
	/*
	 * Dde has decided that we can connect, so it gives us a conversation
	 * handle. We need to keep track of it so we know which execution
	 * result to return in an XTYP_REQUEST.
	 */

	len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0);
	Tcl_DStringInit(&dString);
	Tcl_DStringSetLength(&dString, len);
	utilString = Tcl_DStringValue(&dString);
	DdeQueryString(ddeInstance, ddeTopic, utilString, (DWORD) len + 1,
		CP_WINANSI);
	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (stricmp(riPtr->name, utilString) == 0) {
		convPtr = (Conversation *) ckalloc(sizeof(Conversation));
		convPtr->nextPtr = tsdPtr->currentConversations;
		convPtr->returnPackagePtr = NULL;
		convPtr->hConv = hConv;
		convPtr->riPtr = riPtr;
		tsdPtr->currentConversations = convPtr;
		break;
	    }
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
		    tsdPtr->currentConversations = convPtr->nextPtr;
		} else {
		    prevConvPtr->nextPtr = convPtr->nextPtr;
		}
		if (convPtr->returnPackagePtr != NULL) {
		    Tcl_DecrRefCount(convPtr->returnPackagePtr);
		}
		Tcl_Free((char *) convPtr);
		break;
	    }
	}
	return (HDDEDATA) TRUE;

    case XTYP_REQUEST:
	/*







|







681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
		    tsdPtr->currentConversations = convPtr->nextPtr;
		} else {
		    prevConvPtr->nextPtr = convPtr->nextPtr;
		}
		if (convPtr->returnPackagePtr != NULL) {
		    Tcl_DecrRefCount(convPtr->returnPackagePtr);
		}
		ckfree((char *) convPtr);
		break;
	    }
	}
	return (HDDEDATA) TRUE;

    case XTYP_REQUEST:
	/*
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774

775

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792

793
794
795
796
797

798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if (convPtr != NULL) {
	    Tcl_DString dsBuf;
	    char *returnString;

	    len = DdeQueryStringW(ddeInstance, ddeItem, NULL, 0, CP_WINUNICODE);
	    Tcl_DStringInit(&dString);
	    Tcl_DStringInit(&dsBuf);
	    Tcl_DStringSetLength(&dString, (len + 1) * sizeof(WCHAR) - 1);
	    utilString = (WCHAR *) Tcl_DStringValue(&dString);
	    DdeQueryStringW(ddeInstance, ddeItem, utilString, (DWORD) len + 1,
		    CP_WINUNICODE);
	    if (_wcsicmp(utilString, TCL_DDE_EXECUTE_RESULT) == 0) {

		returnString =
			Tcl_GetString(convPtr->returnPackagePtr);
		len = convPtr->returnPackagePtr->length;
		if (uFmt != CF_TEXT) {
		    Tcl_DStringInit(&dsBuf);
		    Tcl_UtfToWCharDString(returnString, len, &dsBuf);

		    returnString = Tcl_DStringValue(&dsBuf);

		    len = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR) - 1;
		}
		ddeReturn = DdeCreateDataHandle(ddeInstance, (BYTE *)returnString,
			(DWORD) len+1, 0, ddeItem, uFmt, 0);
	    } else {
		if (Tcl_IsSafe(convPtr->riPtr->interp)) {
		    ddeReturn = NULL;
		} else {
		    Tcl_DString ds;
		    Tcl_Obj *variableObjPtr;

		    Tcl_DStringInit(&ds);
		    Tcl_WCharToUtfDString(utilString, wcslen(utilString), &ds);
		    variableObjPtr = Tcl_GetVar2Ex(
			    convPtr->riPtr->interp, Tcl_DStringValue(&ds), NULL,
			    TCL_GLOBAL_ONLY);
		    if (variableObjPtr != NULL) {

			returnString = Tcl_GetString(variableObjPtr);
			len = variableObjPtr->length;
			if (uFmt != CF_TEXT) {
			    Tcl_DStringInit(&dsBuf);
			    Tcl_UtfToWCharDString(returnString, len, &dsBuf);

			    returnString = Tcl_DStringValue(&dsBuf);

			    len = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR) - 1;
			}
			ddeReturn = DdeCreateDataHandle(ddeInstance,
				(BYTE *)returnString, (DWORD) len+1, 0, ddeItem,
				uFmt, 0);
		    } else {
			ddeReturn = NULL;
		    }
		    Tcl_DStringFree(&ds);
		}
	    }
	    Tcl_DStringFree(&dsBuf);
	    Tcl_DStringFree(&dString);
	}
	return ddeReturn;

#if !CBF_FAIL_POKES
    case XTYP_POKE:
	/*
	 * This is a poke for a Tcl variable, only implemented in
	 * debug/UNICODE mode.
	 */
	ddeReturn = DDE_FNOTPROCESSED;

	if ((uFmt != CF_TEXT) && (uFmt != CF_UNICODETEXT)) {
	    return ddeReturn;
	}

	for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if (convPtr && !Tcl_IsSafe(convPtr->riPtr->interp)) {
	    Tcl_DString ds, ds2;
	    Tcl_Obj *variableObjPtr;
	    DWORD len2;

	    Tcl_DStringInit(&dString);
	    Tcl_DStringInit(&ds2);
	    len = DdeQueryStringW(ddeInstance, ddeItem, NULL, 0, CP_WINUNICODE);
	    Tcl_DStringSetLength(&dString, (len + 1) * sizeof(WCHAR) - 1);
	    utilString = (WCHAR *) Tcl_DStringValue(&dString);
	    DdeQueryStringW(ddeInstance, ddeItem, utilString, (DWORD) len + 1,
		    CP_WINUNICODE);
	    Tcl_DStringInit(&ds);
	    Tcl_WCharToUtfDString(utilString, wcslen(utilString), &ds);
	    utilString = (WCHAR *) DdeAccessData(hData, &len2);
	    len = len2;
	    if (uFmt != CF_TEXT) {
		Tcl_DStringInit(&ds2);
		Tcl_WCharToUtfDString(utilString, wcslen(utilString), &ds2);
		utilString = (WCHAR *) Tcl_DStringValue(&ds2);
	    }
	    variableObjPtr = Tcl_NewStringObj((char *)utilString, -1);

	    Tcl_SetVar2Ex(convPtr->riPtr->interp, Tcl_DStringValue(&ds), NULL,
		    variableObjPtr, TCL_GLOBAL_ONLY);

	    Tcl_DStringFree(&ds2);
	    Tcl_DStringFree(&ds);
	    Tcl_DStringFree(&dString);
		ddeReturn = (HDDEDATA) DDE_FACK;
	}
	return ddeReturn;

#endif
    case XTYP_EXECUTE: {
	/*
	 * Execute this script. The results will be saved into a list object
	 * which will be retreived later. See ExecuteRemoteObject.
	 */

	Tcl_Obj *returnPackagePtr;
	char *string;

	for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if (convPtr == NULL) {
	    return (HDDEDATA) DDE_FNOTPROCESSED;
	}

	utilString = (WCHAR *) DdeAccessData(hData, &dlen);
	string = (char *) utilString;
	if (!dlen) {
	    /* Empty binary array. */
	    ddeObjectPtr = Tcl_NewObj();
	} else if ((dlen & 1) || utilString[(dlen>>1)-1]) {
	    /* Cannot be unicode, so assume utf-8 */
	    if (!string[dlen-1]) {
		dlen--;
	    }
	    ddeObjectPtr = Tcl_NewStringObj(string, dlen);
	} else {
	    /* unicode */
	    Tcl_DString dsBuf;

	    Tcl_DStringInit(&dsBuf);
	    Tcl_WCharToUtfDString(utilString, (dlen>>1) - 1, &dsBuf);
	    ddeObjectPtr = Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
		    Tcl_DStringLength(&dsBuf));
	    Tcl_DStringFree(&dsBuf);
	}
	Tcl_IncrRefCount(ddeObjectPtr);
	DdeUnaccessData(hData);
	if (convPtr->returnPackagePtr != NULL) {
	    Tcl_DecrRefCount(convPtr->returnPackagePtr);
	}
	convPtr->returnPackagePtr = NULL;







<


|

<
|
|
|
|
|
>
|
|
<
<
<
<
>
|
>
|







<
|
<
<
<
<
|


>
|
|
<
<
<
>
|
>
|







<


<




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|












|
|



|

|


|


<
|
<
<
|
<
<







707
708
709
710
711
712
713

714
715
716
717

718
719
720
721
722
723
724
725




726
727
728
729
730
731
732
733
734
735
736

737




738
739
740
741
742
743



744
745
746
747
748
749
750
751
752
753
754

755
756

757
758
759
760





















































761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

794


795


796
797
798
799
800
801
802
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if (convPtr != NULL) {

	    char *returnString;

	    len = DdeQueryString(ddeInstance, ddeItem, NULL, 0, CP_WINANSI);
	    Tcl_DStringInit(&dString);

	    Tcl_DStringSetLength(&dString, len);
	    utilString = Tcl_DStringValue(&dString);
	    DdeQueryString(ddeInstance, ddeItem, utilString, (DWORD) len + 1,
		    CP_WINANSI);
	    if (stricmp(utilString, TCL_DDE_EXECUTE_RESULT) == 0) {
		if (uFmt == CF_TEXT) {
		    returnString =
			    Tcl_GetStringFromObj(convPtr->returnPackagePtr, &len);




		} else {
		    returnString = (char *)
			    Tcl_GetUnicodeFromObj(convPtr->returnPackagePtr, &len);
		    len = 2 * len + 1;
		}
		ddeReturn = DdeCreateDataHandle(ddeInstance, (BYTE *)returnString,
			(DWORD) len+1, 0, ddeItem, uFmt, 0);
	    } else {
		if (Tcl_IsSafe(convPtr->riPtr->interp)) {
		    ddeReturn = NULL;
		} else {

		    Tcl_Obj *variableObjPtr = Tcl_GetVar2Ex(




			    convPtr->riPtr->interp, utilString, NULL,
			    TCL_GLOBAL_ONLY);
		    if (variableObjPtr != NULL) {
			if (uFmt == CF_TEXT) {
			    returnString = Tcl_GetStringFromObj(
				    variableObjPtr, &len);



			} else {
			    returnString = (char *) Tcl_GetUnicodeFromObj(
				    variableObjPtr, &len);
			    len = 2 * len + 1;
			}
			ddeReturn = DdeCreateDataHandle(ddeInstance,
				(BYTE *)returnString, (DWORD) len+1, 0, ddeItem,
				uFmt, 0);
		    } else {
			ddeReturn = NULL;
		    }

		}
	    }

	    Tcl_DStringFree(&dString);
	}
	return ddeReturn;






















































    case XTYP_EXECUTE: {
	/*
	 * Execute this script. The results will be saved into a list object
	 * which will be retreived later. See ExecuteRemoteObject.
	 */

	Tcl_Obj *returnPackagePtr;
	Tcl_UniChar *uniStr;

	for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if (convPtr == NULL) {
	    return (HDDEDATA) DDE_FNOTPROCESSED;
	}

	utilString = (char *) DdeAccessData(hData, &dlen);
	uniStr = (Tcl_UniChar *) utilString;
	if (!dlen) {
	    /* Empty binary array. */
	    ddeObjectPtr = Tcl_NewObj();
	} else if ((dlen & 1) || uniStr[(dlen>>1)-1]) {
	    /* Cannot be unicode, so assume utf-8 */
	    if (!utilString[dlen-1]) {
		dlen--;
	    }
	    ddeObjectPtr = Tcl_NewStringObj(utilString, dlen);
	} else {
	    /* unicode */

	    dlen >>= 1;


	    ddeObjectPtr = Tcl_NewUnicodeObj(uniStr, dlen - 1);


	}
	Tcl_IncrRefCount(ddeObjectPtr);
	DdeUnaccessData(hData);
	if (convPtr->returnPackagePtr != NULL) {
	    Tcl_DecrRefCount(convPtr->returnPackagePtr);
	}
	convPtr->returnPackagePtr = NULL;
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
	numItems = i;
	ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
		(numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0);
	returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
	len = dlen;
	for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems;
		i++, riPtr = riPtr->nextPtr) {
	    returnPtr[i].hszSvc = DdeCreateStringHandleW(ddeInstance,
		    TCL_DDE_SERVICE_NAME, CP_WINUNICODE);
	    returnPtr[i].hszTopic = DdeCreateStringHandleW(ddeInstance,
		    riPtr->name, CP_WINUNICODE);
	}
	returnPtr[i].hszSvc = NULL;
	returnPtr[i].hszTopic = NULL;
	DdeUnaccessData(ddeReturn);
	return ddeReturn;
    }








|
|
|
|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
	numItems = i;
	ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
		(numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0);
	returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
	len = dlen;
	for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems;
		i++, riPtr = riPtr->nextPtr) {
	    returnPtr[i].hszSvc = DdeCreateStringHandle(ddeInstance,
		    TCL_DDE_SERVICE_NAME, CP_WINANSI);
	    returnPtr[i].hszTopic = DdeCreateStringHandle(ddeInstance,
		    riPtr->name, CP_WINANSI);
	}
	returnPtr[i].hszSvc = NULL;
	returnPtr[i].hszTopic = NULL;
	DdeUnaccessData(ddeReturn);
	return ddeReturn;
    }

986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
 *	The DDE server is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DdeExitProc(
    void *dummy)		/* Not used. */
{
    (void)dummy;
    DdeNameService(ddeInstance, NULL, 0, DNS_UNREGISTER);
    DdeUninitialize(ddeInstance);
    ddeInstance = 0;
}

/*
 *----------------------------------------------------------------------







|

<







874
875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
 *	The DDE server is deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DdeExitProc(
    ClientData clientData)	    /* Not used in this handler. */
{

    DdeNameService(ddeInstance, NULL, 0, DNS_UNREGISTER);
    DdeUninitialize(ddeInstance);
    ddeInstance = 0;
}

/*
 *----------------------------------------------------------------------
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
 *
 *----------------------------------------------------------------------
 */

static int
MakeDdeConnection(
    Tcl_Interp *interp,		/* Used to report errors. */
    const WCHAR *name,		/* The connection to use. */
    HCONV *ddeConvPtr)
{
    HSZ ddeTopic, ddeService;
    HCONV ddeConv;

    ddeService = DdeCreateStringHandleW(ddeInstance, TCL_DDE_SERVICE_NAME, CP_WINUNICODE);
    ddeTopic = DdeCreateStringHandleW(ddeInstance, name, CP_WINUNICODE);

    ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
    DdeFreeStringHandle(ddeInstance, ddeService);
    DdeFreeStringHandle(ddeInstance, ddeTopic);

    if (ddeConv == (HCONV) NULL) {
	if (interp != NULL) {
	    Tcl_DString dString;

	    Tcl_DStringInit(&dString);
	    Tcl_WCharToUtfDString(name, wcslen(name), &dString);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no registered server named \"%s\"", Tcl_DStringValue(&dString)));
	    Tcl_DStringFree(&dString);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL);
	}
	return TCL_ERROR;
    }

    *ddeConvPtr = ddeConv;
    return TCL_OK;
}







|





|
|







<
<
<
<
<
|
<
|







901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922





923

924
925
926
927
928
929
930
931
 *
 *----------------------------------------------------------------------
 */

static int
MakeDdeConnection(
    Tcl_Interp *interp,		/* Used to report errors. */
    const char *name,		/* The connection to use. */
    HCONV *ddeConvPtr)
{
    HSZ ddeTopic, ddeService;
    HCONV ddeConv;

    ddeService = DdeCreateStringHandle(ddeInstance, TCL_DDE_SERVICE_NAME, 0);
    ddeTopic = DdeCreateStringHandle(ddeInstance, name, 0);

    ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
    DdeFreeStringHandle(ddeInstance, ddeService);
    DdeFreeStringHandle(ddeInstance, ddeTopic);

    if (ddeConv == (HCONV) NULL) {
	if (interp != NULL) {





	    Tcl_AppendResult(interp, "no registered server named \"",

		    name, "\"", NULL);
	}
	return TCL_ERROR;
    }

    *ddeConvPtr = ddeConv;
    return TCL_OK;
}
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
 *	Sets the services list into the interp result.
 *
 *----------------------------------------------------------------------
 */

static int
DdeCreateClient(
    DdeEnumServices *es)
{
    WNDCLASSEXW wc;
    static const WCHAR *szDdeClientClassName = L"TclEval client class";
    static const WCHAR *szDdeClientWindowName = L"TclEval client window";

    memset(&wc, 0, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.lpfnWndProc = DdeClientWindowProc;
    wc.lpszClassName = szDdeClientClassName;
    wc.cbWndExtra = sizeof(DdeEnumServices *);

    /*
     * Register and create the callback window.
     */

    RegisterClassExW(&wc);
    es->hwnd = CreateWindowExW(0, szDdeClientClassName, szDdeClientWindowName,
	    WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, (LPVOID)es);
    return TCL_OK;
}

static LRESULT CALLBACK
DdeClientWindowProc(
    HWND hwnd,			/* What window is the message for */
    UINT uMsg,			/* The type of message received */
    WPARAM wParam,
    LPARAM lParam)		/* (Potentially) our local handle */
{
    switch (uMsg) {
    case WM_CREATE: {
	LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
	DdeEnumServices *es =
		(DdeEnumServices *) lpcs->lpCreateParams;

#ifdef _WIN64
	SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) es);
#else
	SetWindowLongW(hwnd, GWL_USERDATA, (LONG) es);
#endif
	return (LRESULT) 0L;
    }
    case WM_DDE_ACK:
	return DdeServicesOnAck(hwnd, wParam, lParam);
    default:
	return DefWindowProcW(hwnd, uMsg, wParam, lParam);
    }
}

static LRESULT
DdeServicesOnAck(
    HWND hwnd,
    WPARAM wParam,
    LPARAM lParam)
{
    HWND hwndRemote = (HWND)wParam;
    ATOM service = (ATOM)LOWORD(lParam);
    ATOM topic = (ATOM)HIWORD(lParam);
    DdeEnumServices *es;
    WCHAR sz[255];
    Tcl_DString dString;

#ifdef _WIN64
    es = (DdeEnumServices *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
#else
    es = (DdeEnumServices *) GetWindowLongW(hwnd, GWL_USERDATA);
#endif

    if (((es->service == (ATOM)0) || (es->service == service))
	    && ((es->topic == (ATOM)0) || (es->topic == topic))) {
	Tcl_Obj *matchPtr = Tcl_NewListObj(0, NULL);
	Tcl_Obj *resultPtr = Tcl_GetObjResult(es->interp);

	GlobalGetAtomNameW(service, sz, 255);
	Tcl_DStringInit(&dString);
	Tcl_WCharToUtfDString(sz, wcslen(sz), &dString);
	Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(Tcl_DStringValue(&dString), -1));
	Tcl_DStringFree(&dString);
	GlobalGetAtomNameW(topic, sz, 255);
	Tcl_DStringInit(&dString);
	Tcl_WCharToUtfDString(sz, wcslen(sz), &dString);
	Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(Tcl_DStringValue(&dString), -1));
	Tcl_DStringFree(&dString);

	/*
	 * Adding the hwnd as a third list element provides a unique
	 * identifier in the case of multiple servers with the name
	 * application and topic names.
	 */
	/*







|

|
|
|





|





|
|














|
|


|

|






|












|
|
<


|

|


|
|



|
<
<
|
<
|
<
<
|
<







948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027


1028

1029


1030

1031
1032
1033
1034
1035
1036
1037
 *	Sets the services list into the interp result.
 *
 *----------------------------------------------------------------------
 */

static int
DdeCreateClient(
    struct DdeEnumServices *es)
{
    WNDCLASSEX wc;
    static const char *szDdeClientClassName = "TclEval client class";
    static const char *szDdeClientWindowName = "TclEval client window";

    memset(&wc, 0, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.lpfnWndProc = DdeClientWindowProc;
    wc.lpszClassName = szDdeClientClassName;
    wc.cbWndExtra = sizeof(struct DdeEnumServices *);

    /*
     * Register and create the callback window.
     */

    RegisterClassEx(&wc);
    es->hwnd = CreateWindowEx(0, szDdeClientClassName, szDdeClientWindowName,
	    WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, (LPVOID)es);
    return TCL_OK;
}

static LRESULT CALLBACK
DdeClientWindowProc(
    HWND hwnd,			/* What window is the message for */
    UINT uMsg,			/* The type of message received */
    WPARAM wParam,
    LPARAM lParam)		/* (Potentially) our local handle */
{
    switch (uMsg) {
    case WM_CREATE: {
	LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
	struct DdeEnumServices *es =
		(struct DdeEnumServices *) lpcs->lpCreateParams;

#ifdef _WIN64
	SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) es);
#else
	SetWindowLong(hwnd, GWL_USERDATA, (LONG) es);
#endif
	return (LRESULT) 0L;
    }
    case WM_DDE_ACK:
	return DdeServicesOnAck(hwnd, wParam, lParam);
    default:
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

static LRESULT
DdeServicesOnAck(
    HWND hwnd,
    WPARAM wParam,
    LPARAM lParam)
{
    HWND hwndRemote = (HWND)wParam;
    ATOM service = (ATOM)LOWORD(lParam);
    ATOM topic = (ATOM)HIWORD(lParam);
    struct DdeEnumServices *es;
    char sz[255];


#ifdef _WIN64
    es = (struct DdeEnumServices *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
#else
    es = (struct DdeEnumServices *) GetWindowLong(hwnd, GWL_USERDATA);
#endif

    if ((es->service == (ATOM)0 || es->service == service)
	    && (es->topic == (ATOM)0 || es->topic == topic)) {
	Tcl_Obj *matchPtr = Tcl_NewListObj(0, NULL);
	Tcl_Obj *resultPtr = Tcl_GetObjResult(es->interp);

	GlobalGetAtomName(service, sz, 255);


	Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(sz, -1));

	GlobalGetAtomName(topic, sz, 255);


	Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(sz, -1));


	/*
	 * Adding the hwnd as a third list element provides a unique
	 * identifier in the case of multiple servers with the name
	 * application and topic names.
	 */
	/*
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
	}
    }

    /*
     * Tell the server we are no longer interested.
     */

    PostMessageW(hwndRemote, WM_DDE_TERMINATE, (WPARAM)hwnd, 0L);
    return 0L;
}

static BOOL CALLBACK
DdeEnumWindowsCallback(
    HWND hwndTarget,
    LPARAM lParam)
{
    DWORD_PTR dwResult = 0;
    DdeEnumServices *es = (DdeEnumServices *) lParam;

    SendMessageTimeoutW(hwndTarget, WM_DDE_INITIATE, (WPARAM)es->hwnd,
	    MAKELONG(es->service, es->topic), SMTO_ABORTIFHUNG, 1000,
	    &dwResult);
    return TRUE;
}

static int
DdeGetServicesList(
    Tcl_Interp *interp,
    const WCHAR *serviceName,
    const WCHAR *topicName)
{
    DdeEnumServices es;

    es.interp = interp;
    es.result = TCL_OK;
    es.service = (serviceName == NULL)
	    ? (ATOM)0 : GlobalAddAtomW(serviceName);
    es.topic = (topicName == NULL) ? (ATOM)0 : GlobalAddAtomW(topicName);

    Tcl_ResetResult(interp); /* our list is to be appended to result. */
    DdeCreateClient(&es);
    EnumWindows(DdeEnumWindowsCallback, (LPARAM)&es);

    if (IsWindow(es.hwnd)) {
	DestroyWindow(es.hwnd);







|









|

|








|
|

|




|
|







1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
	}
    }

    /*
     * Tell the server we are no longer interested.
     */

    PostMessage(hwndRemote, WM_DDE_TERMINATE, (WPARAM)hwnd, 0L);
    return 0L;
}

static BOOL CALLBACK
DdeEnumWindowsCallback(
    HWND hwndTarget,
    LPARAM lParam)
{
    DWORD_PTR dwResult = 0;
    struct DdeEnumServices *es = (struct DdeEnumServices *) lParam;

    SendMessageTimeout(hwndTarget, WM_DDE_INITIATE, (WPARAM)es->hwnd,
	    MAKELONG(es->service, es->topic), SMTO_ABORTIFHUNG, 1000,
	    &dwResult);
    return TRUE;
}

static int
DdeGetServicesList(
    Tcl_Interp *interp,
    const char *serviceName,
    const char *topicName)
{
    struct DdeEnumServices es;

    es.interp = interp;
    es.result = TCL_OK;
    es.service = (serviceName == NULL)
	    ? (ATOM)0 : GlobalAddAtom(serviceName);
    es.topic = (topicName == NULL) ? (ATOM)0 : GlobalAddAtom(topicName);

    Tcl_ResetResult(interp); /* our list is to be appended to result. */
    DdeCreateClient(&es);
    EnumWindows(DdeEnumWindowsCallback, (LPARAM)&es);

    if (IsWindow(es.hwnd)) {
	DestroyWindow(es.hwnd);
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
 *----------------------------------------------------------------------
 */

static void
SetDdeError(
    Tcl_Interp *interp)	    /* The interp to put the message in. */
{
    const char *errorMessage, *errorCode;

    switch (DdeGetLastError(ddeInstance)) {
    case DMLERR_DATAACKTIMEOUT:
    case DMLERR_EXECACKTIMEOUT:
    case DMLERR_POKEACKTIMEOUT:
	errorMessage = "remote interpreter did not respond";
	errorCode = "TIMEOUT";
	break;
    case DMLERR_BUSY:
	errorMessage = "remote server is busy";
	errorCode = "BUSY";
	break;
    case DMLERR_NOTPROCESSED:
	errorMessage = "remote server cannot handle this command";
	errorCode = "NOCANDO";
	break;
    default:
	errorMessage = "dde command failed";
	errorCode = "FAILED";
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMessage, -1));
    Tcl_SetErrorCode(interp, "TCL", "DDE", errorCode, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * DdeObjCmd --
 *







|






<



<



<



<



<







1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134

1135
1136
1137

1138
1139
1140

1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
 *----------------------------------------------------------------------
 */

static void
SetDdeError(
    Tcl_Interp *interp)	    /* The interp to put the message in. */
{
    const char *errorMessage;

    switch (DdeGetLastError(ddeInstance)) {
    case DMLERR_DATAACKTIMEOUT:
    case DMLERR_EXECACKTIMEOUT:
    case DMLERR_POKEACKTIMEOUT:
	errorMessage = "remote interpreter did not respond";

	break;
    case DMLERR_BUSY:
	errorMessage = "remote server is busy";

	break;
    case DMLERR_NOTPROCESSED:
	errorMessage = "remote server cannot handle this command";

	break;
    default:
	errorMessage = "dde command failed";

    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMessage, -1));

}

/*
 *----------------------------------------------------------------------
 *
 * DdeObjCmd --
 *
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DdeObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const *objv)	/* The arguments */
{
    static const char *const ddeCommands[] = {
	"servername", "execute", "poke", "request", "services", "eval",
	(char *) NULL};
    enum DdeSubcommands {
	DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES,
	DDE_EVAL
    };
    static const char *const ddeSrvOptions[] = {
	"-force", "-handler", "--", NULL
    };
    enum DdeSrvOptions {
	DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST,
    };
    static const char *const ddeExecOptions[] = {
	"-async", "-binary", NULL
    };
    enum DdeExecOptions {
        DDE_EXEC_ASYNC, DDE_EXEC_BINARY
    };
    static const char *const ddeEvalOptions[] = {
	"-async", NULL
    };
    static const char *const ddeReqOptions[] = {
	"-binary", NULL
    };

    int index, i, argIndex;
    size_t length;
    int flags = 0, result = TCL_OK, firstArg = 0;
    HSZ ddeService = NULL, ddeTopic = NULL, ddeItem = NULL, ddeCookie = NULL;
    HDDEDATA ddeData = NULL, ddeItemData = NULL, ddeReturn;
    HCONV hConv = NULL;
    const WCHAR *serviceName = NULL, *topicName = NULL;
    const char *string;
    DWORD ddeResult;
    Tcl_Obj *objPtr, *handlerPtr = NULL;
    Tcl_DString serviceBuf, topicBuf, itemBuf;
    (void)dummy;

    /*
     * Initialize DDE server/client
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], ddeCommands, "command", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_DStringInit(&serviceBuf);
    Tcl_DStringInit(&topicBuf);
    Tcl_DStringInit(&itemBuf);
    switch ((enum DdeSubcommands) index) {
    case DDE_SERVERNAME:
	for (i = 2; i < objc; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], ddeSrvOptions,
		    "option", 0, &argIndex) != TCL_OK) {
		/*
		 * If it is the last argument, it might be a server name







|




|






|





|
<
<
<
<
<
<


|



|
<




|
<


<
<















<
<
<







1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183






1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195

1196
1197


1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212



1213
1214
1215
1216
1217
1218
1219
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DdeObjCmd(
    ClientData clientData,	/* Used only for deletion */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const *objv)	/* The arguments */
{
    static const char *ddeCommands[] = {
	"servername", "execute", "poke", "request", "services", "eval",
	(char *) NULL};
    enum DdeSubcommands {
	DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES,
	DDE_EVAL
    };
    static const char *ddeSrvOptions[] = {
	"-force", "-handler", "--", NULL
    };
    enum DdeSrvOptions {
	DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST,
    };
    static const char *ddeExecOptions[] = {






	"-async", NULL
    };
    static const char *ddeReqOptions[] = {
	"-binary", NULL
    };

    int index, i, length, argIndex;

    int flags = 0, result = TCL_OK, firstArg = 0;
    HSZ ddeService = NULL, ddeTopic = NULL, ddeItem = NULL, ddeCookie = NULL;
    HDDEDATA ddeData = NULL, ddeItemData = NULL, ddeReturn;
    HCONV hConv = NULL;
    const char *serviceName = NULL, *topicName = NULL, *string;

    DWORD ddeResult;
    Tcl_Obj *objPtr, *handlerPtr = NULL;



    /*
     * Initialize DDE server/client
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], ddeCommands, "command", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }




    switch ((enum DdeSubcommands) index) {
    case DDE_SERVERNAME:
	for (i = 2; i < objc; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], ddeSrvOptions,
		    "option", 0, &argIndex) != TCL_OK) {
		/*
		 * If it is the last argument, it might be a server name
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443



1444
1445
1446
1447


1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459

	firstArg = (objc == i) ? 1 : i;
	break;
    case DDE_EXECUTE:
	if (objc == 5) {
	    firstArg = 2;
	    break;
	} else if ((objc >= 6) && (objc <= 7)) {
	    firstArg = objc - 3;
	    for (i = 2; i < firstArg; i++) {
		if (Tcl_GetIndexFromObj(interp, objv[i], ddeExecOptions,
			"option", 0, &argIndex) != TCL_OK) {
		    goto wrongDdeExecuteArgs;
		}
		if (argIndex == DDE_EXEC_ASYNC) {
		    flags |= DDE_FLAG_ASYNC;

		} else {
		    flags |= DDE_FLAG_BINARY;
		}
	    }
	    break;
	}
	/* otherwise... */
    wrongDdeExecuteArgs:
	Tcl_WrongNumArgs(interp, 2, objv,
		"?-async? ?-binary? serviceName topicName value");
	return TCL_ERROR;
    case DDE_POKE:
	if (objc == 6) {
	    firstArg = 2;
	    break;
	} else if ((objc == 7) && (Tcl_GetIndexFromObj(NULL, objv[2],
		ddeReqOptions, "option", 0, &argIndex) == TCL_OK)) {
	    flags |= DDE_FLAG_BINARY;
	    firstArg = 3;
	    break;
	}

	/*
	 * Otherwise...
	 */

	Tcl_WrongNumArgs(interp, 2, objv,
		"?-binary? serviceName topicName item value");
	return TCL_ERROR;



    case DDE_REQUEST:
	if (objc == 5) {
	    firstArg = 2;
	    break;


	} else if ((objc == 6) && (Tcl_GetIndexFromObj(NULL, objv[2],
		ddeReqOptions, "option", 0, &argIndex) == TCL_OK)) {
	    flags |= DDE_FLAG_BINARY;
	    firstArg = 3;
	    break;

	}

	/*
	 * Otherwise ...
	 */

	Tcl_WrongNumArgs(interp, 2, objv,







|
<
<
|
|
<
<
<
|
>
|
<
|
|
<
<

<

|


|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
>
>
>




>
>
|
|
|
|
|
>







1255
1256
1257
1258
1259
1260
1261
1262


1263
1264



1265
1266
1267

1268
1269


1270

1271
1272
1273
1274
1275













1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300

	firstArg = (objc == i) ? 1 : i;
	break;
    case DDE_EXECUTE:
	if (objc == 5) {
	    firstArg = 2;
	    break;
	} else if (objc == 6) {


	    if (Tcl_GetIndexFromObj(NULL, objv[2], ddeExecOptions, "option", 0,
		    &argIndex) == TCL_OK) {



		flags |= DDE_FLAG_ASYNC;
		firstArg = 3;
		break;

	    }
	}


	/* otherwise... */

	Tcl_WrongNumArgs(interp, 2, objv,
		"?-async? serviceName topicName value");
	return TCL_ERROR;
    case DDE_POKE:
	if (objc != 6) {













	    Tcl_WrongNumArgs(interp, 2, objv,
		    "serviceName topicName item value");
	    return TCL_ERROR;
	}
	firstArg = 2;
	break;
    case DDE_REQUEST:
	if (objc == 5) {
	    firstArg = 2;
	    break;
	} else if (objc == 6) {
	    int dummy;
	    if (Tcl_GetIndexFromObj(NULL, objv[2], ddeReqOptions, "option", 0,
		    &dummy) == TCL_OK) {
		flags |= DDE_FLAG_BINARY;
		firstArg = 3;
		break;
	    }
	}

	/*
	 * Otherwise ...
	 */

	Tcl_WrongNumArgs(interp, 2, objv,
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
    case DDE_EVAL:
	if (objc < 4) {
	wrongDdeEvalArgs:
	    Tcl_WrongNumArgs(interp, 2, objv, "?-async? serviceName args");
	    return TCL_ERROR;
	} else {
	    firstArg = 2;
	    if (Tcl_GetIndexFromObj(NULL, objv[2], ddeEvalOptions, "option",
		    0, &argIndex) == TCL_OK) {
		if (objc < 5) {
		    goto wrongDdeEvalArgs;
		}
		flags |= DDE_FLAG_ASYNC;
		firstArg++;
	    }
	    break;
	}
    }

    Initialize();

    if (firstArg != 1) {
	const char *src = Tcl_GetString(objv[firstArg]);

	length = objv[firstArg]->length;
	Tcl_DStringInit(&serviceBuf);
	Tcl_UtfToWCharDString(src, length, &serviceBuf);
	serviceName = (WCHAR *) Tcl_DStringValue(&serviceBuf);
	length = Tcl_DStringLength(&serviceBuf) / sizeof(WCHAR);
    } else {
	length = 0;
    }

    if (length == 0) {
	serviceName = NULL;
    } else if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	ddeService = DdeCreateStringHandleW(ddeInstance, serviceName,
		CP_WINUNICODE);
    }

    if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	const char *src = Tcl_GetString(objv[firstArg + 1]);

	length = objv[firstArg + 1]->length;
	Tcl_DStringInit(&topicBuf);
	topicName = Tcl_UtfToWCharDString(src, length, &topicBuf);
	length = Tcl_DStringLength(&topicBuf) / sizeof(WCHAR);
	if (length == 0) {
	    topicName = NULL;
	} else {
	    ddeTopic = DdeCreateStringHandleW(ddeInstance, topicName,
		    CP_WINUNICODE);
	}
    }

    switch ((enum DdeSubcommands) index) {
    case DDE_SERVERNAME:
	serviceName = DdeSetServerName(interp, serviceName, flags,
		handlerPtr);
	if (serviceName != NULL) {
	    Tcl_DString dsBuf;

	    Tcl_DStringInit(&dsBuf);
	    Tcl_WCharToUtfDString(serviceName, wcslen(serviceName), &dsBuf);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
		    Tcl_DStringLength(&dsBuf)));
	    Tcl_DStringFree(&dsBuf);
	} else {
	    Tcl_ResetResult(interp);
	}
	break;

    case DDE_EXECUTE: {
	size_t dataLength;
	const void *dataString;
	Tcl_DString dsBuf;

	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString =
		    getByteArrayFromObj(objv[firstArg + 2], &dataLength);
	} else {
	    const char *src;

	    src = Tcl_GetString(objv[firstArg + 2]);
	    dataLength = objv[firstArg + 2]->length;
	    Tcl_DStringInit(&dsBuf);
	    dataString =
		    Tcl_UtfToWCharDString(src, dataLength, &dsBuf);
	    dataLength = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	}

	if (dataLength + 1 < 2) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot execute null data", -1));
	    Tcl_DStringFree(&dsBuf);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    result = TCL_ERROR;
	    break;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {
	    Tcl_DStringFree(&dsBuf);
	    SetDdeError(interp);
	    result = TCL_ERROR;
	    break;
	}

	ddeData = DdeCreateDataHandle(ddeInstance, (BYTE *) dataString,
		(DWORD) dataLength, 0, 0, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, 0);
	if (ddeData != NULL) {
	    if (flags & DDE_FLAG_ASYNC) {
		DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0,
			(flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
		DdeAbandonTransaction(ddeInstance, hConv, ddeResult);
	    } else {
		ddeReturn = DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF,
			hConv, 0, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_EXECUTE, 30000, NULL);
		if (ddeReturn == 0) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		}
	    }
	    DdeFreeDataHandle(ddeData);
	} else {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	}
	Tcl_DStringFree(&dsBuf);
	break;
    }
    case DDE_REQUEST: {
	const WCHAR *itemString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	length = objv[firstArg + 2]->length;
	Tcl_DStringInit(&itemBuf);
	itemString = Tcl_UtfToWCharDString(src, length, &itemBuf);
	length = Tcl_DStringLength(&itemBuf) / sizeof(WCHAR);

	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot request value of null data", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	} else {
	    Tcl_Obj *returnObjPtr;
	    ddeItem = DdeCreateStringHandleW(ddeInstance, itemString,
		    CP_WINUNICODE);
	    if (ddeItem != NULL) {
		ddeData = DdeClientTransaction(NULL, 0, hConv, ddeItem,
			(flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_REQUEST, 5000, NULL);
		if (ddeData == NULL) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		} else {
		    DWORD tmp;
		    WCHAR *dataString = (WCHAR *) DdeAccessData(ddeData, &tmp);

		    if (flags & DDE_FLAG_BINARY) {
			returnObjPtr =
				Tcl_NewByteArrayObj((BYTE *) dataString, tmp);
		    } else {
			Tcl_DString dsBuf;

			if ((tmp >= sizeof(WCHAR))
				&& !dataString[tmp / sizeof(WCHAR) - 1]) {
			    tmp -= sizeof(WCHAR);
			}
			Tcl_DStringInit(&dsBuf);
			Tcl_WCharToUtfDString(dataString, tmp>>1, &dsBuf);
			returnObjPtr =
			    Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
				    Tcl_DStringLength(&dsBuf));
			Tcl_DStringFree(&dsBuf);
		    }
		    DdeUnaccessData(ddeData);
		    DdeFreeDataHandle(ddeData);
		    Tcl_SetObjResult(interp, returnObjPtr);
		}
	    } else {
		SetDdeError(interp);
		result = TCL_ERROR;
	    }
	}

	break;
    }
    case DDE_POKE: {
	Tcl_DString dsBuf;
	const WCHAR *itemString;
	BYTE *dataString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	length = objv[firstArg + 2]->length;
	Tcl_DStringInit(&itemBuf);
	itemString = Tcl_UtfToWCharDString(src, length, &itemBuf);
	length = Tcl_DStringLength(&itemBuf) / sizeof(WCHAR);
	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot have a null item", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString = (BYTE *)
		    getByteArrayFromObj(objv[firstArg + 3], &length);
	} else {
	    const char *data =
		    Tcl_GetString(objv[firstArg + 3]);
	    length = objv[firstArg + 3]->length;
	    Tcl_DStringInit(&dsBuf);
	    dataString = (BYTE *)
		    Tcl_UtfToWCharDString(data, length, &dsBuf);
	    length = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	}

	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	} else {
	    ddeItem = DdeCreateStringHandleW(ddeInstance, itemString,
		    CP_WINUNICODE);
	    if (ddeItem != NULL) {
		ddeData = DdeClientTransaction(dataString, (DWORD) length,
			hConv, ddeItem, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_POKE, 5000, NULL);
		if (ddeData == NULL) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		}
	    } else {
		SetDdeError(interp);
		result = TCL_ERROR;
	    }
	}
	Tcl_DStringFree(&dsBuf);
	break;
    }

    case DDE_SERVICES:
	result = DdeGetServicesList(interp, serviceName, topicName);
	break;

    case DDE_EVAL: {
	RegisteredInterp *riPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	if (serviceName == NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("invalid service name \"\"", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}

	objc -= firstArg + 1;
	objv += firstArg + 1;

	/*
	 * See if the target interpreter is local. If so, execute the command
	 * directly without going through the DDE server. Don't exchange
	 * objects between interps. The target interp could compile an object,
	 * producing a bytecode structure that refers to other objects owned
	 * by the target interp. If the target interp is then deleted, the
	 * bytecode structure would be referring to deallocated objects.
	 */

	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (_wcsicmp(serviceName, riPtr->name) == 0) {
		break;
	    }
	}

	if (riPtr != NULL) {
	    Tcl_Interp *sendInterp;

	    /*
	     * This command is to a local interp. No need to go through the
	     * server.
	     */

	    Tcl_Preserve(riPtr);
	    sendInterp = riPtr->interp;
	    Tcl_Preserve(sendInterp);

	    /*
	     * Don't exchange objects between interps. The target interp would
	     * compile an object, producing a bytecode structure that refers
	     * to other objects owned by the target interp. If the target
	     * interp is then deleted, the bytecode structure would be
	     * referring to deallocated objects.
	     */

	    if (Tcl_IsSafe(riPtr->interp) && (riPtr->handlerPtr == NULL)) {
		Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj(
			"permission denied: a handler procedure must be"
			" defined for use in a safe interp", -1));
		Tcl_SetErrorCode(interp, "TCL", "DDE", "SECURITY_CHECK",
			NULL);
		result = TCL_ERROR;
	    }

	    if (result == TCL_OK) {
		if (objc == 1)
		    objPtr = objv[0];
		else {







|














<
|
<
<
<
<
<







|
|



|
<
<
<
<
<



|
|








<
<
<
<
|
<
<






|
<
<
<
<
<
|
|
<
<

<
<
<
<
<
<
<
<
|


<
<








<





|
|



|



|










<



<
|
|
<
<
<
<
<




<












|
|


|





|



|

<
<
<
|
|

<
<
|
<
<
|










>



|
|

<

<
<
<
<
<



<



<
<
|
|
<
<
<
<
<
<
<
<
<









|
|

|
|









<














<


















|












|

|









|
|
|
|
<
<







1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331

1332





1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345





1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358




1359


1360
1361
1362
1363
1364
1365
1366





1367
1368


1369








1370
1371
1372


1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408

1409
1410





1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442



1443
1444
1445


1446


1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464

1465





1466
1467
1468

1469
1470
1471


1472
1473









1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557


1558
1559
1560
1561
1562
1563
1564
    case DDE_EVAL:
	if (objc < 4) {
	wrongDdeEvalArgs:
	    Tcl_WrongNumArgs(interp, 2, objv, "?-async? serviceName args");
	    return TCL_ERROR;
	} else {
	    firstArg = 2;
	    if (Tcl_GetIndexFromObj(NULL, objv[2], ddeExecOptions, "option",
		    0, &argIndex) == TCL_OK) {
		if (objc < 5) {
		    goto wrongDdeEvalArgs;
		}
		flags |= DDE_FLAG_ASYNC;
		firstArg++;
	    }
	    break;
	}
    }

    Initialize();

    if (firstArg != 1) {

	serviceName = Tcl_GetStringFromObj(objv[firstArg], &length);





    } else {
	length = 0;
    }

    if (length == 0) {
	serviceName = NULL;
    } else if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	ddeService = DdeCreateStringHandle(ddeInstance, (void *) serviceName,
		CP_WINANSI);
    }

    if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	topicName = Tcl_GetStringFromObj(objv[firstArg + 1], &length);





	if (length == 0) {
	    topicName = NULL;
	} else {
	    ddeTopic = DdeCreateStringHandle(ddeInstance, (void *) topicName,
		    CP_WINANSI);
	}
    }

    switch ((enum DdeSubcommands) index) {
    case DDE_SERVERNAME:
	serviceName = DdeSetServerName(interp, serviceName, flags,
		handlerPtr);
	if (serviceName != NULL) {




	    Tcl_SetObjResult(interp, Tcl_NewStringObj(serviceName, -1));


	} else {
	    Tcl_ResetResult(interp);
	}
	break;

    case DDE_EXECUTE: {
	int dataLength;





	BYTE *dataString = (BYTE *) Tcl_GetStringFromObj(
		objv[firstArg + 2], &dataLength);











	if (dataLength == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot execute null data", -1));


	    result = TCL_ERROR;
	    break;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {

	    SetDdeError(interp);
	    result = TCL_ERROR;
	    break;
	}

	ddeData = DdeCreateDataHandle(ddeInstance, dataString,
		(DWORD) dataLength+1, 0, 0, CF_TEXT, 0);
	if (ddeData != NULL) {
	    if (flags & DDE_FLAG_ASYNC) {
		DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0,
			CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
		DdeAbandonTransaction(ddeInstance, hConv, ddeResult);
	    } else {
		ddeReturn = DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF,
			hConv, 0, CF_TEXT, XTYP_EXECUTE, 30000, NULL);
		if (ddeReturn == 0) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		}
	    }
	    DdeFreeDataHandle(ddeData);
	} else {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	}

	break;
    }
    case DDE_REQUEST: {

	const char *itemString = Tcl_GetStringFromObj(objv[firstArg + 2],
		&length);






	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot request value of null data", -1));

	    result = TCL_ERROR;
	    goto cleanup;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	} else {
	    Tcl_Obj *returnObjPtr;
	    ddeItem = DdeCreateStringHandle(ddeInstance, (void *)itemString,
		    CP_WINANSI);
	    if (ddeItem != NULL) {
		ddeData = DdeClientTransaction(NULL, 0, hConv, ddeItem,
			CF_TEXT, XTYP_REQUEST, 5000, NULL);
		if (ddeData == NULL) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		} else {
		    DWORD tmp;
		    const char *dataString = (const char *) DdeAccessData(ddeData, &tmp);

		    if (flags & DDE_FLAG_BINARY) {
			returnObjPtr =
				Tcl_NewByteArrayObj((BYTE *) dataString, (int) tmp);
		    } else {



			if (tmp && !dataString[tmp-1]) {
			    --tmp;
			}


			returnObjPtr = Tcl_NewStringObj(dataString,


				(int) tmp);
		    }
		    DdeUnaccessData(ddeData);
		    DdeFreeDataHandle(ddeData);
		    Tcl_SetObjResult(interp, returnObjPtr);
		}
	    } else {
		SetDdeError(interp);
		result = TCL_ERROR;
	    }
	}

	break;
    }
    case DDE_POKE: {
	const char *itemString = Tcl_GetStringFromObj(objv[firstArg + 2],
		&length);
	BYTE *dataString;







	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot have a null item", -1));

	    result = TCL_ERROR;
	    goto cleanup;
	}


	dataString = (BYTE *) Tcl_GetStringFromObj(objv[firstArg + 3],
		&length);










	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

	if (hConv == NULL) {
	    SetDdeError(interp);
	    result = TCL_ERROR;
	} else {
	    ddeItem = DdeCreateStringHandle(ddeInstance, (void *) itemString,
		    CP_WINANSI);
	    if (ddeItem != NULL) {
		ddeData = DdeClientTransaction(dataString, (DWORD) length+1,
			hConv, ddeItem, CF_TEXT, XTYP_POKE, 5000, NULL);
		if (ddeData == NULL) {
		    SetDdeError(interp);
		    result = TCL_ERROR;
		}
	    } else {
		SetDdeError(interp);
		result = TCL_ERROR;
	    }
	}

	break;
    }

    case DDE_SERVICES:
	result = DdeGetServicesList(interp, serviceName, topicName);
	break;

    case DDE_EVAL: {
	RegisteredInterp *riPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	if (serviceName == NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("invalid service name \"\"", -1));

	    result = TCL_ERROR;
	    goto cleanup;
	}

	objc -= firstArg + 1;
	objv += firstArg + 1;

	/*
	 * See if the target interpreter is local. If so, execute the command
	 * directly without going through the DDE server. Don't exchange
	 * objects between interps. The target interp could compile an object,
	 * producing a bytecode structure that refers to other objects owned
	 * by the target interp. If the target interp is then deleted, the
	 * bytecode structure would be referring to deallocated objects.
	 */

	for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		riPtr = riPtr->nextPtr) {
	    if (stricmp(serviceName, riPtr->name) == 0) {
		break;
	    }
	}

	if (riPtr != NULL) {
	    Tcl_Interp *sendInterp;

	    /*
	     * This command is to a local interp. No need to go through the
	     * server.
	     */

	    Tcl_Preserve((ClientData) riPtr);
	    sendInterp = riPtr->interp;
	    Tcl_Preserve((ClientData) sendInterp);

	    /*
	     * Don't exchange objects between interps. The target interp would
	     * compile an object, producing a bytecode structure that refers
	     * to other objects owned by the target interp. If the target
	     * interp is then deleted, the bytecode structure would be
	     * referring to deallocated objects.
	     */

	    if (Tcl_IsSafe(riPtr->interp) && riPtr->handlerPtr == NULL) {
		Tcl_SetResult(riPtr->interp, "permission denied: "
			"a handler procedure must be defined for use in "
			"a safe interp", TCL_STATIC);


		result = TCL_ERROR;
	    }

	    if (result == TCL_OK) {
		if (objc == 1)
		    objPtr = objv[0];
		else {
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905

1906

1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934


1935
1936
1937
1938
1939
1940
1941
1942
		     * the destination interpreter back to our interpreter.
		     */

		    Tcl_ResetResult(interp);
		    objPtr = Tcl_GetVar2Ex(sendInterp, "errorInfo", NULL,
			    TCL_GLOBAL_ONLY);
		    if (objPtr) {

			Tcl_AppendObjToErrorInfo(interp, objPtr);
		    }

		    objPtr = Tcl_GetVar2Ex(sendInterp, "errorCode", NULL,
			    TCL_GLOBAL_ONLY);
		    if (objPtr) {
			Tcl_SetObjErrorCode(interp, objPtr);
		    }
		}
		Tcl_SetObjResult(interp, Tcl_GetObjResult(sendInterp));
	    }
	    Tcl_Release(riPtr);
	    Tcl_Release(sendInterp);
	} else {
	    Tcl_DString dsBuf;

	    /*
	     * This is a non-local request. Send the script to the server and
	     * poll it for a result.
	     */

	    if (MakeDdeConnection(interp, serviceName, &hConv) != TCL_OK) {
	    invalidServerResponse:
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("invalid data returned from server", -1));
		Tcl_SetErrorCode(interp, "TCL", "DDE", "BAD_RESPONSE", NULL);
		result = TCL_ERROR;
		goto cleanup;
	    }

	    objPtr = Tcl_ConcatObj(objc, objv);
	    string = Tcl_GetString(objPtr);
	    length = objPtr->length;
	    Tcl_DStringInit(&dsBuf);
	    Tcl_UtfToWCharDString(string, length, &dsBuf);
	    string = Tcl_DStringValue(&dsBuf);
	    length = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	    ddeItemData = DdeCreateDataHandle(ddeInstance, (BYTE *) string,
		    (DWORD) length, 0, 0, CF_UNICODETEXT, 0);
	    Tcl_DStringFree(&dsBuf);

	    if (flags & DDE_FLAG_ASYNC) {
		ddeData = DdeClientTransaction((LPBYTE) ddeItemData,
			0xFFFFFFFF, hConv, 0,
			CF_UNICODETEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
		DdeAbandonTransaction(ddeInstance, hConv, ddeResult);
	    } else {
		ddeData = DdeClientTransaction((LPBYTE) ddeItemData,
			0xFFFFFFFF, hConv, 0,
			CF_UNICODETEXT, XTYP_EXECUTE, 30000, NULL);
		if (ddeData != 0) {
		    ddeCookie = DdeCreateStringHandleW(ddeInstance,
			    TCL_DDE_EXECUTE_RESULT, CP_WINUNICODE);
		    ddeData = DdeClientTransaction(NULL, 0, hConv, ddeCookie,
			    CF_UNICODETEXT, XTYP_REQUEST, 30000, NULL);
		}
	    }

	    Tcl_DecrRefCount(objPtr);

	    if (ddeData == 0) {
		SetDdeError(interp);
		result = TCL_ERROR;
		goto cleanup;
	    }

	    if (!(flags & DDE_FLAG_ASYNC)) {
		Tcl_Obj *resultPtr;
		WCHAR *ddeDataString;

		/*
		 * The return handle has a two or four element list in it. The
		 * first element is the return code (TCL_OK, TCL_ERROR, etc.).
		 * The second is the result of the script. If the return code
		 * is TCL_ERROR, then the third element is the value of the
		 * variable "errorCode", and the fourth is the value of the
		 * variable "errorInfo".
		 */


		length = DdeGetData(ddeData, NULL, 0, 0);

		ddeDataString = (WCHAR *) Tcl_Alloc(length);
		DdeGetData(ddeData, (BYTE *) ddeDataString, (DWORD) length, 0);
		if (length > sizeof(WCHAR)) {
		    length -= sizeof(WCHAR);
		}
		Tcl_DStringInit(&dsBuf);
		Tcl_WCharToUtfDString(ddeDataString, length>>1, &dsBuf);
		resultPtr = Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
			Tcl_DStringLength(&dsBuf));
		Tcl_DStringFree(&dsBuf);
		Tcl_Free((char *) ddeDataString);

		if (Tcl_ListObjIndex(NULL, resultPtr, 0, &objPtr) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;
		}
		if (Tcl_GetIntFromObj(NULL, objPtr, &result) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;
		}
		if (result == TCL_ERROR) {
		    Tcl_ResetResult(interp);

		    if (Tcl_ListObjIndex(NULL, resultPtr, 3,
			    &objPtr) != TCL_OK) {
			Tcl_DecrRefCount(resultPtr);
			goto invalidServerResponse;
		    }


		    Tcl_AppendObjToErrorInfo(interp, objPtr);

		    Tcl_ListObjIndex(NULL, resultPtr, 2, &objPtr);
		    Tcl_SetObjErrorCode(interp, objPtr);
		}
		if (Tcl_ListObjIndex(NULL, resultPtr, 1, &objPtr) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;







>
|










|
|

<
<








|
|





|
<
<
<
<
<
|
|
<




|




|

|
|

|








<




<










>

>
|
|
<
<
<
<
<
<
|
<
<

















>
>
|







1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611


1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627





1628
1629

1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671






1672


1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
		     * the destination interpreter back to our interpreter.
		     */

		    Tcl_ResetResult(interp);
		    objPtr = Tcl_GetVar2Ex(sendInterp, "errorInfo", NULL,
			    TCL_GLOBAL_ONLY);
		    if (objPtr) {
			string = Tcl_GetStringFromObj(objPtr, &length);
			Tcl_AddObjErrorInfo(interp, string, length);
		    }

		    objPtr = Tcl_GetVar2Ex(sendInterp, "errorCode", NULL,
			    TCL_GLOBAL_ONLY);
		    if (objPtr) {
			Tcl_SetObjErrorCode(interp, objPtr);
		    }
		}
		Tcl_SetObjResult(interp, Tcl_GetObjResult(sendInterp));
	    }
	    Tcl_Release((ClientData) riPtr);
	    Tcl_Release((ClientData) sendInterp);
	} else {


	    /*
	     * This is a non-local request. Send the script to the server and
	     * poll it for a result.
	     */

	    if (MakeDdeConnection(interp, serviceName, &hConv) != TCL_OK) {
	    invalidServerResponse:
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("invalid data returned from server",
			-1));
		result = TCL_ERROR;
		goto cleanup;
	    }

	    objPtr = Tcl_ConcatObj(objc, objv);
	    string = Tcl_GetStringFromObj(objPtr, &length);





	    ddeItemData = DdeCreateDataHandle(ddeInstance,
		    (BYTE *) string, (DWORD) length+1, 0, 0, CF_TEXT, 0);


	    if (flags & DDE_FLAG_ASYNC) {
		ddeData = DdeClientTransaction((LPBYTE) ddeItemData,
			0xFFFFFFFF, hConv, 0,
			CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
		DdeAbandonTransaction(ddeInstance, hConv, ddeResult);
	    } else {
		ddeData = DdeClientTransaction((LPBYTE) ddeItemData,
			0xFFFFFFFF, hConv, 0,
			CF_TEXT, XTYP_EXECUTE, 30000, NULL);
		if (ddeData != 0) {
		    ddeCookie = DdeCreateStringHandle(ddeInstance,
			    TCL_DDE_EXECUTE_RESULT, CP_WINANSI);
		    ddeData = DdeClientTransaction(NULL, 0, hConv, ddeCookie,
			    CF_TEXT, XTYP_REQUEST, 30000, NULL);
		}
	    }

	    Tcl_DecrRefCount(objPtr);

	    if (ddeData == 0) {
		SetDdeError(interp);
		result = TCL_ERROR;

	    }

	    if (!(flags & DDE_FLAG_ASYNC)) {
		Tcl_Obj *resultPtr;


		/*
		 * The return handle has a two or four element list in it. The
		 * first element is the return code (TCL_OK, TCL_ERROR, etc.).
		 * The second is the result of the script. If the return code
		 * is TCL_ERROR, then the third element is the value of the
		 * variable "errorCode", and the fourth is the value of the
		 * variable "errorInfo".
		 */

		resultPtr = Tcl_NewObj();
		length = DdeGetData(ddeData, NULL, 0, 0);
		Tcl_SetObjLength(resultPtr, length);
		string = Tcl_GetString(resultPtr);
		DdeGetData(ddeData, (BYTE *) string, (DWORD) length, 0);






		Tcl_SetObjLength(resultPtr, (int) strlen(string));



		if (Tcl_ListObjIndex(NULL, resultPtr, 0, &objPtr) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;
		}
		if (Tcl_GetIntFromObj(NULL, objPtr, &result) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;
		}
		if (result == TCL_ERROR) {
		    Tcl_ResetResult(interp);

		    if (Tcl_ListObjIndex(NULL, resultPtr, 3,
			    &objPtr) != TCL_OK) {
			Tcl_DecrRefCount(resultPtr);
			goto invalidServerResponse;
		    }
		    length = -1;
		    string = Tcl_GetStringFromObj(objPtr, &length);
		    Tcl_AddObjErrorInfo(interp, string, length);

		    Tcl_ListObjIndex(NULL, resultPtr, 2, &objPtr);
		    Tcl_SetObjErrorCode(interp, objPtr);
		}
		if (Tcl_ListObjIndex(NULL, resultPtr, 1, &objPtr) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    goto invalidServerResponse;
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
    }
    if (ddeData != NULL) {
	DdeFreeDataHandle(ddeData);
    }
    if (hConv != NULL) {
	DdeDisconnect(hConv);
    }
    Tcl_DStringFree(&itemBuf);
    Tcl_DStringFree(&topicBuf);
    Tcl_DStringFree(&serviceBuf);
    return result;
}

/*
 * Local variables:
 * mode: c
 * indent-tabs-mode: t
 * tab-width: 8
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







<
<
<












1717
1718
1719
1720
1721
1722
1723



1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
    }
    if (ddeData != NULL) {
	DdeFreeDataHandle(ddeData);
    }
    if (hConv != NULL) {
	DdeDisconnect(hConv);
    }



    return result;
}

/*
 * Local variables:
 * mode: c
 * indent-tabs-mode: t
 * tab-width: 8
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinFile.c.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
 */

#include "tclWinInt.h"
#include "tclFileSystem.h"
#include <winioctl.h>
#include <shlobj.h>
#include <lmaccess.h>		/* For TclpGetUserHome(). */


/*
 * The number of 100-ns intervals between the Windows system epoch (1601-01-01
 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01).
 */

#define POSIX_EPOCH_AS_FILETIME	\







>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 */

#include "tclWinInt.h"
#include "tclFileSystem.h"
#include <winioctl.h>
#include <shlobj.h>
#include <lmaccess.h>		/* For TclpGetUserHome(). */
#include <userenv.h>		/* For TclpGetUserHome(). */

/*
 * The number of 100-ns intervals between the Windows system epoch (1601-01-01
 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01).
 */

#define POSIX_EPOCH_AS_FILETIME	\
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
 *
 *	In the future we should enhance this to return a path object rather
 *	than a string.
 *
 *--------------------------------------------------------------------
 */

#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif

static Tcl_Obj *
WinReadLinkDirectory(
    const TCHAR *linkDirPath)
{
    int attr, len, offset;
    DUMMY_REPARSE_BUFFER dummy;
    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy;







<
<
<
<
<







565
566
567
568
569
570
571





572
573
574
575
576
577
578
 *
 *	In the future we should enhance this to return a path object rather
 *	than a string.
 *
 *--------------------------------------------------------------------
 */






static Tcl_Obj *
WinReadLinkDirectory(
    const TCHAR *linkDirPath)
{
    int attr, len, offset;
    DUMMY_REPARSE_BUFFER dummy;
    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
	return retVal;
    }

  invalidError:
    Tcl_SetErrno(EINVAL);
    return NULL;
}

#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#endif

/*
 *--------------------------------------------------------------------
 *
 * NativeReadReparse --
 *
 *	Read the junction/reparse information from a given NTFS directory.







<
<
<
<







680
681
682
683
684
685
686




687
688
689
690
691
692
693
	return retVal;
    }

  invalidError:
    Tcl_SetErrno(EINVAL);
    return NULL;
}





/*
 *--------------------------------------------------------------------
 *
 * NativeReadReparse --
 *
 *	Read the junction/reparse information from a given NTFS directory.
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
    char name[MAX_PATH * TCL_UTF_MAX];

    /*
     * Under Windows we ignore argv0, and return the path for the file used to
     * create this process.
     */

    if (GetModuleFileNameW(NULL, wName, sizeof(wName)/sizeof(WCHAR)) == 0) {
	GetModuleFileNameA(NULL, name, sizeof(name));

	/*
	 * Convert to WCHAR to get out of ANSI codepage
	 */

	MultiByteToWideChar(CP_ACP, 0, name, -1, wName, MAX_PATH);







|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
    char name[MAX_PATH * TCL_UTF_MAX];

    /*
     * Under Windows we ignore argv0, and return the path for the file used to
     * create this process.
     */

    if (GetModuleFileNameW(NULL, wName, MAX_PATH) == 0) {
	GetModuleFileNameA(NULL, name, sizeof(name));

	/*
	 * Convert to WCHAR to get out of ANSI codepage
	 */

	MultiByteToWideChar(CP_ACP, 0, name, -1, wName, MAX_PATH);
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
	    }
	    handle = LoadLibraryA("userenv.dll");
	    if (handle) {
		getProfilesDirectoryProc = (GETPROFILESDIRECTORYPROC *)
			GetProcAddress(handle, "GetProfilesDirectoryW");
		Tcl_CreateExitHandler(FreeLoadLibHandle, handle);
	    }

	    apistubs = -1;
	    if ( (netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL)
	      && (netApiBufferFreeProc != NULL) && (getProfilesDirectoryProc != NULL)
	    ) {
		apistubs = 1;
	    }
	}







|







1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
	    }
	    handle = LoadLibraryA("userenv.dll");
	    if (handle) {
		getProfilesDirectoryProc = (GETPROFILESDIRECTORYPROC *)
			GetProcAddress(handle, "GetProfilesDirectoryW");
		Tcl_CreateExitHandler(FreeLoadLibHandle, handle);
	    }
	    
	    apistubs = -1;
	    if ( (netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL)
	      && (netApiBufferFreeProc != NULL) && (getProfilesDirectoryProc != NULL)
	    ) {
		apistubs = 1;
	    }
	}
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504

	rc = 0;
	nameLen = -1;
	wDomain = NULL;
	domain = Tcl_UtfFindFirst(name, '@');
	if (domain == NULL) {
	    const char *ptr;

	    /* no domain - firstly check it's the current user */
	    if ( (ptr = TclpGetUserName(&ds)) != NULL
	      && strcasecmp(name, ptr) == 0
	    ) {
		/* try safest and fastest way to get current user home */
		ptr = TclGetEnv("HOME", &ds);
		if (ptr != NULL) {
		    Tcl_JoinPath(1, &ptr, bufferPtr);
		    rc = 1;







|

|







1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

	rc = 0;
	nameLen = -1;
	wDomain = NULL;
	domain = Tcl_UtfFindFirst(name, '@');
	if (domain == NULL) {
	    const char *ptr;
	    
	    /* no domain - firstly check it's the current user */
	    if ( (ptr = TclpGetUserName(&ds)) != NULL 
	      && strcasecmp(name, ptr) == 0
	    ) {
		/* try safest and fastest way to get current user home */
		ptr = TclGetEnv("HOME", &ds);
		if (ptr != NULL) {
		    Tcl_JoinPath(1, &ptr, bufferPtr);
		    rc = 1;
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
	    nameLen = domain - name;
	}
	if (rc == 0) {
	    Tcl_DStringInit(&ds);
	    wName = Tcl_UtfToUniCharDString(name, nameLen, &ds);
	    while ((netUserGetInfoProc)(wDomain, wName, 1,
		    (LPBYTE *) &uiPtr) != 0) {
		/*
		 * user does not exists - if domain was not specified,
		 * try again using current domain.
		 */
		rc = 1;
		if (domain != NULL) break;
		/* get current domain */
		rc = (netGetDCNameProc)(NULL, NULL, (LPBYTE *) &wDomain);







|







1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
	    nameLen = domain - name;
	}
	if (rc == 0) {
	    Tcl_DStringInit(&ds);
	    wName = Tcl_UtfToUniCharDString(name, nameLen, &ds);
	    while ((netUserGetInfoProc)(wDomain, wName, 1,
		    (LPBYTE *) &uiPtr) != 0) {
		/* 
		 * user does not exists - if domain was not specified,
		 * try again using current domain.
		 */
		rc = 1;
		if (domain != NULL) break;
		/* get current domain */
		rc = (netGetDCNameProc)(NULL, NULL, (LPBYTE *) &wDomain);
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
	/*
	 * File exists, nothing else to check.
	 */

	return 0;
    }

    /*
     * If it's not a directory (assume file), do several fast checks:
     */
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
	/*
	 * If the attributes say this is not writable at all.  The file is a
	 * regular file (i.e., not a directory), then the file is not
	 * writable, full stop.	 For directories, the read-only bit is







|







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
	/*
	 * File exists, nothing else to check.
	 */

	return 0;
    }

    /* 
     * If it's not a directory (assume file), do several fast checks:
     */
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
	/*
	 * If the attributes say this is not writable at all.  The file is a
	 * regular file (i.e., not a directory), then the file is not
	 * writable, full stop.	 For directories, the read-only bit is
1887
1888
1889
1890
1891
1892
1893

1894
1895
1896
1897
1898
1899
1900
	 * Use wide-char case-insensitive comparison
	 */

	path += len-3;
	if ((_wcsicmp(path, L"exe") == 0)
		|| (_wcsicmp(path, L"com") == 0)
		|| (_wcsicmp(path, L"cmd") == 0)

		|| (_wcsicmp(path, L"bat") == 0)) {
	    return 1;
	}
    } else {
	const char *p;

	/*







>







1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
	 * Use wide-char case-insensitive comparison
	 */

	path += len-3;
	if ((_wcsicmp(path, L"exe") == 0)
		|| (_wcsicmp(path, L"com") == 0)
		|| (_wcsicmp(path, L"cmd") == 0)
		|| (_wcsicmp(path, L"ps1") == 0)
		|| (_wcsicmp(path, L"bat") == 0)) {
	    return 1;
	}
    } else {
	const char *p;

	/*
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
     * fileHandle to read more information (nlink, ino) than we can get from
     * other attributes reading APIs. If not, then we try to fall back on the
     * 'getFileAttributesExProc', and if that isn't available, then on even
     * simpler routines.
     */

    fileHandle = (tclWinProcs->createFileProc)(nativePath, GENERIC_READ,
	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
	    NULL, OPEN_EXISTING,
	    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);

    if (fileHandle != INVALID_HANDLE_VALUE) {
	BY_HANDLE_FILE_INFORMATION data;

	if (GetFileInformationByHandle(fileHandle,&data) != TRUE) {







|







2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
     * fileHandle to read more information (nlink, ino) than we can get from
     * other attributes reading APIs. If not, then we try to fall back on the
     * 'getFileAttributesExProc', and if that isn't available, then on even
     * simpler routines.
     */

    fileHandle = (tclWinProcs->createFileProc)(nativePath, GENERIC_READ,
	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
	    NULL, OPEN_EXISTING,
	    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);

    if (fileHandle != INVALID_HANDLE_VALUE) {
	BY_HANDLE_FILE_INFORMATION data;

	if (GetFileInformationByHandle(fileHandle,&data) != TRUE) {

Changes to win/tclWinInit.c.

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


#define NUMPLATFORMS 4
static char* platforms[NUMPLATFORMS] = {
    "Win32s", "Windows 95", "Windows NT", "Windows CE"
};

#define NUMPROCESSORS 15
static char* processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};

/*
 * The default directory in which the init.tcl file is expected to be found.
 */

static TclInitProcessGlobalValueProc	InitializeDefaultLibraryDir;







|


|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


#define NUMPLATFORMS 4
static char* platforms[NUMPLATFORMS] = {
    "Win32s", "Windows 95", "Windows NT", "Windows CE"
};

#define NUMPROCESSORS 11
static char* processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
};

/*
 * The default directory in which the init.tcl file is expected to be found.
 */

static TclInitProcessGlobalValueProc	InitializeDefaultLibraryDir;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
static int		ToUtf(CONST WCHAR *wSrc, char *dst);

/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependent things like signals,
 *	floating-point error handling and sockets.
 *
 *	Called at process initialization time.
 *
 * Results:
 *	None.
 *







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
static int		ToUtf(CONST WCHAR *wSrc, char *dst);

/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependant things like signals,
 *	floating-point error handling and sockets.
 *
 *	Called at process initialization time.
 *
 * Results:
 *	None.
 *
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
InitializeDefaultLibraryDir(
    char **valuePtr,
    int *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * 3];
    char *end, *p;

    if (GetModuleFileNameW(hModule, wName, sizeof(wName)/sizeof(WCHAR)) == 0) {
	GetModuleFileNameA(hModule, name, sizeof(name));
    } else {
	ToUtf(wName, name);
    }

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');







|


|
|







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
InitializeDefaultLibraryDir(
    char **valuePtr,
    int *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX];
    char *end, *p;

    if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
	GetModuleFileNameA(hModule, name, MAX_PATH);
    } else {
	ToUtf(wName, name);
    }

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
InitializeSourceLibraryDir(
    char **valuePtr,
    int *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * 3];
    char *end, *p;

    if (GetModuleFileNameW(hModule, wName, sizeof(wName)/sizeof(WCHAR)) == 0) {
	GetModuleFileNameA(hModule, name, sizeof(name));
    } else {
	ToUtf(wName, name);
    }

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');







|


|
|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
InitializeSourceLibraryDir(
    char **valuePtr,
    int *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX];
    char *end, *p;

    if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) {
	GetModuleFileNameA(hModule, name, MAX_PATH);
    } else {
	ToUtf(wName, name);
    }

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');

Changes to win/tclWinInt.h.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef VER_PLATFORM_WIN32_WINDOWS
#define VER_PLATFORM_WIN32_WINDOWS 1
#endif
#ifndef VER_PLATFORM_WIN32_CE
#define VER_PLATFORM_WIN32_CE 3
#endif

#ifndef TCL_Z_MODIFIER
#   ifdef _WIN64
#	if defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO
#         define TCL_Z_MODIFIER        "ll"
#	else
#         define TCL_Z_MODIFIER        "I"
#	endif
#   else
#         define TCL_Z_MODIFIER        ""
#   endif
#endif
#define TCL_I_MODIFIER TCL_Z_MODIFIER

/*
 * The following structure keeps track of whether we are using the
 * multi-byte or the wide-character interfaces to the operating system.
 * System calls should be made through the following function table.
 */

typedef union {
    WIN32_FIND_DATAA a;
    WIN32_FIND_DATAW w;
} WIN32_FIND_DATAT;

typedef struct TclWinProcs {
    int useWide;

    BOOL (WINAPI *buildCommDCBProc)(CONST TCHAR *, LPDCB);
    TCHAR *(WINAPI *charLowerProc)(TCHAR *);
    BOOL (WINAPI *copyFileProc)(CONST TCHAR *, CONST TCHAR *, BOOL);
    BOOL (WINAPI *createDirectoryProc)(CONST TCHAR *, LPSECURITY_ATTRIBUTES);
    HANDLE (WINAPI *createFileProc)(CONST TCHAR *, DWORD, DWORD,
	    LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
    BOOL (WINAPI *createProcessProc)(CONST TCHAR *, TCHAR *,
	    LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD,
	    LPVOID, CONST TCHAR *, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
    BOOL (WINAPI *deleteFileProc)(CONST TCHAR *);
    HANDLE (WINAPI *findFirstFileProc)(CONST TCHAR *, WIN32_FIND_DATAT *);
    BOOL (WINAPI *findNextFileProc)(HANDLE, WIN32_FIND_DATAT *);
    BOOL (WINAPI *getComputerNameProc)(WCHAR *, LPDWORD);
    DWORD (WINAPI *getCurrentDirectoryProc)(DWORD, WCHAR *);
    DWORD (WINAPI *getFileAttributesProc)(CONST TCHAR *);
    DWORD (WINAPI *getFullPathNameProc)(CONST TCHAR *, DWORD nBufferLength,
	    WCHAR *, TCHAR **);
    DWORD (WINAPI *getModuleFileNameProc)(HMODULE, WCHAR *, int);
    DWORD (WINAPI *getShortPathNameProc)(CONST TCHAR *, WCHAR *, DWORD);
    UINT (WINAPI *getTempFileNameProc)(CONST TCHAR *, CONST TCHAR *, UINT,
	    WCHAR *);
    DWORD (WINAPI *getTempPathProc)(DWORD, WCHAR *);
    BOOL (WINAPI *getVolumeInformationProc)(CONST TCHAR *, WCHAR *, DWORD,
	    LPDWORD, LPDWORD, LPDWORD, WCHAR *, DWORD);
    HINSTANCE (WINAPI *loadLibraryExProc)(CONST TCHAR *, HANDLE, DWORD);
    TCHAR (WINAPI *lstrcpyProc)(WCHAR *, CONST TCHAR *);
    BOOL (WINAPI *moveFileProc)(CONST TCHAR *, CONST TCHAR *);
    BOOL (WINAPI *removeDirectoryProc)(CONST TCHAR *);
    DWORD (WINAPI *searchPathProc)(CONST TCHAR *, CONST TCHAR *,
	    CONST TCHAR *, DWORD, WCHAR *, TCHAR **);
    BOOL (WINAPI *setCurrentDirectoryProc)(CONST TCHAR *);
    BOOL (WINAPI *setFileAttributesProc)(CONST TCHAR *, DWORD);
    /*
     * These two function pointers will only be set when
     * Tcl_FindExecutable is called.  If you don't ever call that
     * function, the application will crash whenever WinTcl tries to call
     * functions through these null pointers.  That is not a bug in Tcl
     * -- Tcl_FindExecutable is obligatory in recent Tcl releases.
     */
    BOOL (WINAPI *getFileAttributesExProc)(CONST TCHAR *,
	    GET_FILEEX_INFO_LEVELS, LPVOID);
    BOOL (WINAPI *createHardLinkProc)(CONST TCHAR*, CONST TCHAR*,
				      LPSECURITY_ATTRIBUTES);

    /* deleted INT (__cdecl *utimeProc)(CONST TCHAR*, struct _utimbuf *); */
    /* These two are also NULL at start; see comment above */
    HANDLE (WINAPI *findFirstFileExProc)(CONST TCHAR*, UINT,
					 LPVOID, UINT,
					 LPVOID, DWORD);
    BOOL (WINAPI *getVolumeNameForVMPProc)(CONST TCHAR*, TCHAR*, DWORD);
    DWORD (WINAPI *getLongPathNameProc)(CONST TCHAR*, TCHAR*, DWORD);
    /*
     * These six are for the security sdk to get correct file
     * permissions on NT, 2000, XP, etc.  On 95,98,ME they are
     * always null.
     */
    BOOL (WINAPI *getFileSecurityProc)(LPCTSTR lpFileName,
		     SECURITY_INFORMATION RequestedInformation,
		     PSECURITY_DESCRIPTOR pSecurityDescriptor,
		     DWORD nLength,
		     LPDWORD lpnLengthNeeded);
    BOOL (WINAPI *impersonateSelfProc) (SECURITY_IMPERSONATION_LEVEL
		      ImpersonationLevel);
    BOOL (WINAPI *openThreadTokenProc) (HANDLE ThreadHandle,
		      DWORD DesiredAccess, BOOL OpenAsSelf,
		      PHANDLE TokenHandle);
    BOOL (WINAPI *revertToSelfProc) (void);
    VOID (WINAPI *mapGenericMaskProc) (PDWORD AccessMask,
		      PGENERIC_MAPPING GenericMapping);







<
|
<
|
|
|
<
<
<
<

<


|
















|

|
|







|


|
|


|





|



|






|

|

|







|







|

|







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef VER_PLATFORM_WIN32_WINDOWS
#define VER_PLATFORM_WIN32_WINDOWS 1
#endif
#ifndef VER_PLATFORM_WIN32_CE
#define VER_PLATFORM_WIN32_CE 3
#endif


#ifdef _WIN64

#         define TCL_I_MODIFIER        "I"
#else
#         define TCL_I_MODIFIER        ""




#endif


/*
 * The following structure keeps track of whether we are using the 
 * multi-byte or the wide-character interfaces to the operating system.
 * System calls should be made through the following function table.
 */

typedef union {
    WIN32_FIND_DATAA a;
    WIN32_FIND_DATAW w;
} WIN32_FIND_DATAT;

typedef struct TclWinProcs {
    int useWide;

    BOOL (WINAPI *buildCommDCBProc)(CONST TCHAR *, LPDCB);
    TCHAR *(WINAPI *charLowerProc)(TCHAR *);
    BOOL (WINAPI *copyFileProc)(CONST TCHAR *, CONST TCHAR *, BOOL);
    BOOL (WINAPI *createDirectoryProc)(CONST TCHAR *, LPSECURITY_ATTRIBUTES);
    HANDLE (WINAPI *createFileProc)(CONST TCHAR *, DWORD, DWORD, 
	    LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
    BOOL (WINAPI *createProcessProc)(CONST TCHAR *, TCHAR *, 
	    LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, 
	    LPVOID, CONST TCHAR *, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
    BOOL (WINAPI *deleteFileProc)(CONST TCHAR *);
    HANDLE (WINAPI *findFirstFileProc)(CONST TCHAR *, WIN32_FIND_DATAT *);
    BOOL (WINAPI *findNextFileProc)(HANDLE, WIN32_FIND_DATAT *);
    BOOL (WINAPI *getComputerNameProc)(WCHAR *, LPDWORD);
    DWORD (WINAPI *getCurrentDirectoryProc)(DWORD, WCHAR *);
    DWORD (WINAPI *getFileAttributesProc)(CONST TCHAR *);
    DWORD (WINAPI *getFullPathNameProc)(CONST TCHAR *, DWORD nBufferLength, 
	    WCHAR *, TCHAR **);
    DWORD (WINAPI *getModuleFileNameProc)(HMODULE, WCHAR *, int);
    DWORD (WINAPI *getShortPathNameProc)(CONST TCHAR *, WCHAR *, DWORD); 
    UINT (WINAPI *getTempFileNameProc)(CONST TCHAR *, CONST TCHAR *, UINT, 
	    WCHAR *);
    DWORD (WINAPI *getTempPathProc)(DWORD, WCHAR *);
    BOOL (WINAPI *getVolumeInformationProc)(CONST TCHAR *, WCHAR *, DWORD, 
	    LPDWORD, LPDWORD, LPDWORD, WCHAR *, DWORD);
    HINSTANCE (WINAPI *loadLibraryExProc)(CONST TCHAR *, HANDLE, DWORD);
    TCHAR (WINAPI *lstrcpyProc)(WCHAR *, CONST TCHAR *);
    BOOL (WINAPI *moveFileProc)(CONST TCHAR *, CONST TCHAR *);
    BOOL (WINAPI *removeDirectoryProc)(CONST TCHAR *);
    DWORD (WINAPI *searchPathProc)(CONST TCHAR *, CONST TCHAR *, 
	    CONST TCHAR *, DWORD, WCHAR *, TCHAR **);
    BOOL (WINAPI *setCurrentDirectoryProc)(CONST TCHAR *);
    BOOL (WINAPI *setFileAttributesProc)(CONST TCHAR *, DWORD);
    /* 
     * These two function pointers will only be set when
     * Tcl_FindExecutable is called.  If you don't ever call that
     * function, the application will crash whenever WinTcl tries to call
     * functions through these null pointers.  That is not a bug in Tcl
     * -- Tcl_FindExecutable is obligatory in recent Tcl releases.
     */
    BOOL (WINAPI *getFileAttributesExProc)(CONST TCHAR *, 
	    GET_FILEEX_INFO_LEVELS, LPVOID);
    BOOL (WINAPI *createHardLinkProc)(CONST TCHAR*, CONST TCHAR*, 
				      LPSECURITY_ATTRIBUTES);
    
    /* deleted INT (__cdecl *utimeProc)(CONST TCHAR*, struct _utimbuf *); */
    /* These two are also NULL at start; see comment above */
    HANDLE (WINAPI *findFirstFileExProc)(CONST TCHAR*, UINT,
					 LPVOID, UINT,
					 LPVOID, DWORD);
    BOOL (WINAPI *getVolumeNameForVMPProc)(CONST TCHAR*, TCHAR*, DWORD);
    DWORD (WINAPI *getLongPathNameProc)(CONST TCHAR*, TCHAR*, DWORD);
    /* 
     * These six are for the security sdk to get correct file
     * permissions on NT, 2000, XP, etc.  On 95,98,ME they are
     * always null.
     */
    BOOL (WINAPI *getFileSecurityProc)(LPCTSTR lpFileName,
		     SECURITY_INFORMATION RequestedInformation,
		     PSECURITY_DESCRIPTOR pSecurityDescriptor,
		     DWORD nLength, 
		     LPDWORD lpnLengthNeeded);
    BOOL (WINAPI *impersonateSelfProc) (SECURITY_IMPERSONATION_LEVEL 
		      ImpersonationLevel);
    BOOL (WINAPI *openThreadTokenProc) (HANDLE ThreadHandle,
		      DWORD DesiredAccess, BOOL OpenAsSelf,
		      PHANDLE TokenHandle);
    BOOL (WINAPI *revertToSelfProc) (void);
    VOID (WINAPI *mapGenericMaskProc) (PDWORD AccessMask,
		      PGENERIC_MAPPING GenericMapping);
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
MODULE_SCOPE Tcl_Channel TclWinOpenSerialChannel(HANDLE handle,
			    char *channelName, int permissions);
MODULE_SCOPE void	TclWinResetInterfaceEncodings();
MODULE_SCOPE HANDLE	TclWinSerialOpen(HANDLE handle, CONST TCHAR *name,
			    DWORD access);
MODULE_SCOPE int	TclWinSymLinkCopyDirectory(CONST TCHAR* LinkOriginal,
			    CONST TCHAR* LinkCopy);
MODULE_SCOPE int	TclWinSymLinkDelete(CONST TCHAR* LinkOriginal,
			    int linkOnly);
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
MODULE_SCOPE void	TclWinFreeAllocCache(void);
MODULE_SCOPE void	TclFreeAllocCache(void *);
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
MODULE_SCOPE void *	TclpGetAllocCache(void);
MODULE_SCOPE void	TclpSetAllocCache(void *);







|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
MODULE_SCOPE Tcl_Channel TclWinOpenSerialChannel(HANDLE handle,
			    char *channelName, int permissions);
MODULE_SCOPE void	TclWinResetInterfaceEncodings();
MODULE_SCOPE HANDLE	TclWinSerialOpen(HANDLE handle, CONST TCHAR *name,
			    DWORD access);
MODULE_SCOPE int	TclWinSymLinkCopyDirectory(CONST TCHAR* LinkOriginal,
			    CONST TCHAR* LinkCopy);
MODULE_SCOPE int	TclWinSymLinkDelete(CONST TCHAR* LinkOriginal, 
			    int linkOnly);
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
MODULE_SCOPE void	TclWinFreeAllocCache(void);
MODULE_SCOPE void	TclFreeAllocCache(void *);
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
MODULE_SCOPE void *	TclpGetAllocCache(void);
MODULE_SCOPE void	TclpSetAllocCache(void *);

Changes to win/tclWinPipe.c.

1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
	QuoteCmdLineBackslash(dsPtr, start, special, NULL);
	start = special;
    } else {
	/* rest before first backslash and backslashes into new quoted block */
	QuoteCmdLineBackslash(dsPtr, start, *bspos, NULL);
	start = *bspos;
    }
    /*
     * escape all special chars enclosed in quotes like `"..."`, note that here we
     * don't must escape `\` (with `\`), because it's outside of the main quotes,
     * so `\` remains `\`, but important - not at end of part, because results as
     * before the quote,  so `%\%\` should be escaped as `"%\%"\\`).
     */
    Tcl_DStringAppend(dsPtr, "\"", 1); /* opening escape quote-char */
    do {
    	*bspos = NULL;
	special++;
	if (*special == '\\') {







|
|

|







1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
	QuoteCmdLineBackslash(dsPtr, start, special, NULL);
	start = special;
    } else {
	/* rest before first backslash and backslashes into new quoted block */
	QuoteCmdLineBackslash(dsPtr, start, *bspos, NULL);
	start = *bspos;
    }
    /* 
     * escape all special chars enclosed in quotes like `"..."`, note that here we 
     * don't must escape `\` (with `\`), because it's outside of the main quotes,
     * so `\` remains `\`, but important - not at end of part, because results as 
     * before the quote,  so `%\%\` should be escaped as `"%\%"\\`).
     */
    Tcl_DStringAppend(dsPtr, "\"", 1); /* opening escape quote-char */
    do {
    	*bspos = NULL;
	special++;
	if (*special == '\\') {
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
				 * command line (TCHAR). */
{
    const char *arg, *start, *special, *bspos;
    int quote = 0, i;
    Tcl_DString ds;

    /* characters to enclose in quotes if unpaired quote flag set */
    static const char specMetaChars[] = "&|^<>!()%";
    /* character to enclose in quotes in any case (regardless unpaired-flag) */
    static const char specMetaChars2[] = "%";

    /* Quote flags:
     *   CL_ESCAPE   - escape argument;
     *   CL_QUOTE    - enclose in quotes;
     *   CL_UNPAIRED - previous arguments chain contains unpaired quote-char;
     */
    enum {CL_ESCAPE = 1, CL_QUOTE = 2, CL_UNPAIRED = 4};







|
|
|







1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
				 * command line (TCHAR). */
{
    const char *arg, *start, *special, *bspos;
    int quote = 0, i;
    Tcl_DString ds;

    /* characters to enclose in quotes if unpaired quote flag set */
    const static char *specMetaChars = "&|^<>!()%";
    /* characters to enclose in quotes in any case (regardless unpaired-flag) */
    const static char *specMetaChars2 = "%";

    /* Quote flags:
     *   CL_ESCAPE   - escape argument;
     *   CL_QUOTE    - enclose in quotes;
     *   CL_UNPAIRED - previous arguments chain contains unpaired quote-char;
     */
    enum {CL_ESCAPE = 1, CL_QUOTE = 2, CL_UNPAIRED = 4};
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
		    continue;
		}
		/* other not special (and not meta) character */
		bspos = NULL; /* reset last backslash possition (not interesting) */
		special++;
	    }
	    /* rest of argument (and escape backslashes before closing main quote) */
	    QuoteCmdLineBackslash(&ds, start, special,
	    	(quote & CL_QUOTE) ? bspos : NULL);
	}
	if (quote & CL_QUOTE) {
	    /* end of argument (main closing quote-char) */
	    Tcl_DStringAppend(&ds, "\"", 1);
	}
    }







|







1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
		    continue;
		}
		/* other not special (and not meta) character */
		bspos = NULL; /* reset last backslash possition (not interesting) */
		special++;
	    }
	    /* rest of argument (and escape backslashes before closing main quote) */
	    QuoteCmdLineBackslash(&ds, start, special, 
	    	(quote & CL_QUOTE) ? bspos : NULL);
	}
	if (quote & CL_QUOTE) {
	    /* end of argument (main closing quote-char) */
	    Tcl_DStringAppend(&ds, "\"", 1);
	}
    }
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
    /*
     * For backward compatibility with previous versions of Tcl, we use
     * "file%d" as the base name for pipes even though it would be more
     * natural to use "pipe%d". Use the pointer to keep the channel names
     * unique, in case channels share handles (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t)infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    (ClientData) infoPtr, infoPtr->validMask);

    /*
     * Pipes have AUTO translation mode on Windows and ^Z eof char, which
     * means that a ^Z will be appended to them at close. This is needed for
     * Windows programs that expect a ^Z at EOF.







|







1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
    /*
     * For backward compatibility with previous versions of Tcl, we use
     * "file%d" as the base name for pipes even though it would be more
     * natural to use "pipe%d". Use the pointer to keep the channel names
     * unique, in case channels share handles (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t)infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    (ClientData) infoPtr, infoPtr->validMask);

    /*
     * Pipes have AUTO translation mode on Windows and ^Z eof char, which
     * means that a ^Z will be appended to them at close. This is needed for
     * Windows programs that expect a ^Z at EOF.
2778
2779
2780
2781
2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_PidObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{







>







2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_PidObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{

Changes to win/tclWinPort.h.

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
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLWINPORT
#define _TCLWINPORT

#if !defined(_WIN64) && !defined(__MINGW_USE_VC2005_COMPAT)
/* See [Bug 3354324]: file mtime sets wrong time */
#   define __MINGW_USE_VC2005_COMPAT
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

/* Compatibility to older visual studio / windows platform SDK */
#if !defined(MAXULONG_PTR)
typedef DWORD DWORD_PTR;
typedef DWORD_PTR * PDWORD_PTR;
#endif

/*
 * Ask for the winsock function typedefs, also.
 */
#ifndef INCL_WINSOCK_API_TYPEDEFS
#   define INCL_WINSOCK_API_TYPEDEFS   1
#endif
#include <winsock2.h>

#ifdef CHECK_UNICODE_CALLS
#   define _UNICODE
#   define UNICODE
#   define __TCHAR_DEFINED
    typedef float *_TCHAR;







|

|















<
|
<







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
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLWINPORT
#define _TCLWINPORT

#ifndef _WIN64
/* See [Bug 3354324]: file mtime sets wrong time */
#   define _USE_32BIT_TIME_T
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

/* Compatibility to older visual studio / windows platform SDK */
#if !defined(MAXULONG_PTR)
typedef DWORD DWORD_PTR;
typedef DWORD_PTR * PDWORD_PTR;
#endif

/*
 * Ask for the winsock function typedefs, also.
 */

#define INCL_WINSOCK_API_TYPEDEFS   1

#include <winsock2.h>

#ifdef CHECK_UNICODE_CALLS
#   define _UNICODE
#   define UNICODE
#   define __TCHAR_DEFINED
    typedef float *_TCHAR;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <errno.h>
#include <fcntl.h>
#include <float.h>
#include <malloc.h>
#include <process.h>
#include <signal.h>
#include <string.h>
#if HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#include <limits.h>

#ifndef __GNUC__
#    define strncasecmp _strnicmp
#    define strcasecmp _stricmp
#endif








<
<
<







58
59
60
61
62
63
64



65
66
67
68
69
70
71
#include <errno.h>
#include <fcntl.h>
#include <float.h>
#include <malloc.h>
#include <process.h>
#include <signal.h>
#include <string.h>



#include <limits.h>

#ifndef __GNUC__
#    define strncasecmp _strnicmp
#    define strcasecmp _stricmp
#endif

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#endif

/*
 * Supply definitions for macros to query wait status, if not already
 * defined in header files above.
 */

#ifdef TCL_UNION_WAIT
#   define WAIT_STATUS_TYPE union wait
#else
#   define WAIT_STATUS_TYPE int
#endif /* TCL_UNION_WAIT */

#ifndef WIFEXITED
#   define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xC0000000) == 0)
#endif

#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat) (*((int *) &(stat)))
#endif

#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) ((*((int *) &(stat))) & 0xC0000000)
#endif

#ifndef WTERMSIG
#   define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7F)
#endif

#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)  0
#endif

#ifndef WSTOPSIG
#   define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xFF)
#endif

/*
 * Define constants for waitpid() system call if they aren't defined
 * by a system header file.
 */








|


















|







|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#endif

/*
 * Supply definitions for macros to query wait status, if not already
 * defined in header files above.
 */

#if TCL_UNION_WAIT
#   define WAIT_STATUS_TYPE union wait
#else
#   define WAIT_STATUS_TYPE int
#endif /* TCL_UNION_WAIT */

#ifndef WIFEXITED
#   define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xC0000000) == 0)
#endif

#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat) (*((int *) &(stat)))
#endif

#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) ((*((int *) &(stat))) & 0xC0000000)
#endif

#ifndef WTERMSIG
#   define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7f)
#endif

#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)  0
#endif

#ifndef WSTOPSIG
#   define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xff)
#endif

/*
 * Define constants for waitpid() system call if they aren't defined
 * by a system header file.
 */

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#   define MAXPATHLEN MAXPATH
#endif /* MAXPATHLEN */

/*
 * Define pid_t and uid_t if they're not already defined.
 */

#if !defined(TCL_PID_T)
#   define pid_t int
#endif /* !TCL_PID_T */
#if !defined(TCL_UID_T)
#   define uid_t int
#endif /* !TCL_UID_T */

/*
 * Visual C++ has some odd names for common functions, so we need to
 * define a few macros to handle them.  Also, it defines EDEADLOCK and
 * EDEADLK as the same value, which confuses Tcl_ErrnoId().







|


|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#   define MAXPATHLEN MAXPATH
#endif /* MAXPATHLEN */

/*
 * Define pid_t and uid_t if they're not already defined.
 */

#if ! TCL_PID_T
#   define pid_t int
#endif /* !TCL_PID_T */
#if ! TCL_UID_T
#   define uid_t int
#endif /* !TCL_UID_T */

/*
 * Visual C++ has some odd names for common functions, so we need to
 * define a few macros to handle them.  Also, it defines EDEADLOCK and
 * EDEADLK as the same value, which confuses Tcl_ErrnoId().
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403


/*
 * MSVC 8.0 started to mark many standard C library functions depreciated
 * including the *printf family and others. Tell it to shut up.
 * (_MSC_VER is 1200 for VC6, 1300 or 1310 for vc7.net, 1400 for 8.0)
 */
#if defined(_MSC_VER)
#   pragma warning(disable:4146)
#   pragma warning(disable:4244)
#   if _MSC_VER >= 1400
#	pragma warning(disable:4267)
#	pragma warning(disable:4311)
#	pragma warning(disable:4312)
#	pragma warning(disable:4996)
#   endif
#endif


/*
 * There is no platform-specific panic routine for Windows in the Tcl internals.
 */

#define TclpPanic ((Tcl_PanicProc *) NULL)








|
<

<
|
<
<
|
<

>







375
376
377
378
379
380
381
382

383

384


385

386
387
388
389
390
391
392
393
394


/*
 * MSVC 8.0 started to mark many standard C library functions depreciated
 * including the *printf family and others. Tell it to shut up.
 * (_MSC_VER is 1200 for VC6, 1300 or 1310 for vc7.net, 1400 for 8.0)
 */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)

#   pragma warning(disable:4244)

#   pragma warning(disable:4267)


#   pragma warning(disable:4996)

#endif


/*
 * There is no platform-specific panic routine for Windows in the Tcl internals.
 */

#define TclpPanic ((Tcl_PanicProc *) NULL)

Changes to win/tclWinReg.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"

#ifdef _MSC_VER
#   pragma comment (lib, "advapi32.lib")
#endif
#include <stdlib.h>

/*


 * Ensure that we can say which registry is being accessed.
 */

#ifndef KEY_WOW64_64KEY
#   define KEY_WOW64_64KEY	(0x0100)
#endif
#ifndef KEY_WOW64_32KEY
#   define KEY_WOW64_32KEY	(0x0200)
#endif

/*
 * The maximum length of a sub-key name.
 */

#ifndef MAX_KEY_LENGTH
#   define MAX_KEY_LENGTH	256
#endif

/*
 * The following macros convert between different endian ints.
 */

#define SWAPWORD(x)	MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x)	MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))

/*
 * The following flag is used in OpenKeys to indicate that the specified key
 * should be created if it doesn't currently exist.
 */

#define REG_CREATE 1

/*
 * The following tables contain the mapping from registry root names to the
 * system predefined keys.
 */

static const char *const rootKeyNames[] = {
    "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT",
    "HKEY_CURRENT_USER", "HKEY_CURRENT_CONFIG",
    "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA", NULL
};

static const HKEY rootKeys[] = {
    HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,
    HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA
};

static const char REGISTRY_ASSOC_KEY[] = "registry::command";

/*
 * The following table maps from registry types to strings. Note that the
 * indices for this array are the same as the constants for the known registry
 * types so we don't need a separate table to hold the mapping.
 */

static const char *const typeNames[] = {
    "none", "sz", "expand_sz", "binary", "dword",
    "dword_big_endian", "link", "multi_sz", "resource_list", NULL
};

static DWORD lastType = REG_RESOURCE_LIST;












































































/*
 * Declarations for functions defined in this file.
 */

static void		AppendSystemError(Tcl_Interp *interp, DWORD error);
static int		BroadcastValue(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static DWORD		ConvertDWORD(DWORD type, DWORD value);
static void		DeleteCmd(void *clientData);
static int		DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    REGSAM mode);
static int		DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, REGSAM mode);
static int		GetKeyNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *patternObj, REGSAM mode);
static int		GetType(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, REGSAM mode);
static int		GetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, REGSAM mode);
static int		GetValueNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *patternObj, REGSAM mode);
static int		OpenKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    REGSAM mode, int flags, HKEY *keyPtr);
static DWORD		OpenSubKey(char *hostName, HKEY rootKey,
			    char *keyName, REGSAM mode, int flags,
			    HKEY *keyPtr);
static int		ParseKeyName(Tcl_Interp *interp, char *name,
			    char **hostNamePtr, HKEY *rootKeyPtr,
			    char **keyNamePtr);
static DWORD		RecursiveDeleteKey(HKEY hStartKey,
			    const WCHAR * pKeyName, REGSAM mode);
static int		RegistryObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, Tcl_Obj *dataObj,
			    Tcl_Obj *typeObj, REGSAM mode);

#if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#endif

static unsigned char *
getByteArrayFromObj(
	Tcl_Obj *objPtr,
	size_t *lengthPtr
) {
    int length;

    unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, &length);
#if TCL_MAJOR_VERSION > 8
    if (sizeof(TCL_HASH_TYPE) > sizeof(int)) {
	/* 64-bit and TIP #494 situation: */
	 *lengthPtr = *(TCL_HASH_TYPE *) objPtr->internalRep.twoPtrValue.ptr1;
    } else
#endif
	/* 32-bit or without TIP #494 */
    *lengthPtr = (size_t) (unsigned) length;
    return result;
}

#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT int		Registry_Init(Tcl_Interp *interp);
DLLEXPORT int		Registry_Unload(Tcl_Interp *interp, int flags);
#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Registry_Init --
 *
 *	This function initializes the registry command.







<
<
<
<

>






>
>
|


|
|
<
<
<
<






|






|
|













|










|







|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|

|
|
<

|

|

|

|

|









|
|

|


|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<







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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
































196
197



198
199
200
201
202
203
204
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */





#include "tclInt.h"
#include "tclPort.h"
#ifdef _MSC_VER
#   pragma comment (lib, "advapi32.lib")
#endif
#include <stdlib.h>

/*
 * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
 * Registry_Init declaration is in the source file itself, which is only
 * accessed when we are building a library.
 */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT





/*
 * The maximum length of a sub-key name.
 */

#ifndef MAX_KEY_LENGTH
#define MAX_KEY_LENGTH		256
#endif

/*
 * The following macros convert between different endian ints.
 */

#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))

/*
 * The following flag is used in OpenKeys to indicate that the specified key
 * should be created if it doesn't currently exist.
 */

#define REG_CREATE 1

/*
 * The following tables contain the mapping from registry root names to the
 * system predefined keys.
 */

static CONST char *rootKeyNames[] = {
    "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT",
    "HKEY_CURRENT_USER", "HKEY_CURRENT_CONFIG",
    "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA", NULL
};

static const HKEY rootKeys[] = {
    HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,
    HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA
};

static CONST char REGISTRY_ASSOC_KEY[] = "registry::command";

/*
 * The following table maps from registry types to strings. Note that the
 * indices for this array are the same as the constants for the known registry
 * types so we don't need a separate table to hold the mapping.
 */

static CONST char *typeNames[] = {
    "none", "sz", "expand_sz", "binary", "dword",
    "dword_big_endian", "link", "multi_sz", "resource_list", NULL
};

static DWORD lastType = REG_RESOURCE_LIST;

/*
 * The following structures allow us to select between the Unicode and ASCII
 * interfaces at run time based on whether Unicode APIs are available. The
 * Unicode APIs are preferable because they will handle characters outside of
 * the current code page.
 */

typedef struct RegWinProcs {
    int useWide;

    LONG (WINAPI *regConnectRegistryProc)(CONST TCHAR *, HKEY, PHKEY);
    LONG (WINAPI *regCreateKeyExProc)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
	    DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *, DWORD *);
    LONG (WINAPI *regDeleteKeyProc)(HKEY, CONST TCHAR *);
    LONG (WINAPI *regDeleteValueProc)(HKEY, CONST TCHAR *);
    LONG (WINAPI *regEnumKeyProc)(HKEY, DWORD, TCHAR *, DWORD);
    LONG (WINAPI *regEnumKeyExProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    TCHAR *, DWORD *, FILETIME *);
    LONG (WINAPI *regEnumValueProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    DWORD *, BYTE *, DWORD *);
    LONG (WINAPI *regOpenKeyExProc)(HKEY, CONST TCHAR *, DWORD, REGSAM,
	    HKEY *);
    LONG (WINAPI *regQueryValueExProc)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
	    BYTE *, DWORD *);
    LONG (WINAPI *regSetValueExProc)(HKEY, CONST TCHAR *, DWORD, DWORD,
	    CONST BYTE*, DWORD);
} RegWinProcs;

static RegWinProcs *regWinProcs;

static RegWinProcs asciiProcs = {
    0,

    (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
	    DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *,
	    DWORD *)) RegCreateKeyExA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueA,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyA,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExA,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    DWORD *, BYTE *, DWORD *)) RegEnumValueA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM,
	    HKEY *)) RegOpenKeyExA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
	    BYTE *, DWORD *)) RegQueryValueExA,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD,
	    CONST BYTE*, DWORD)) RegSetValueExA,
};

static RegWinProcs unicodeProcs = {
    1,

    (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
	    DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *,
	    DWORD *)) RegCreateKeyExW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueW,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyW,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExW,
    (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
	    DWORD *, BYTE *, DWORD *)) RegEnumValueW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM,
	    HKEY *)) RegOpenKeyExW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
	    BYTE *, DWORD *)) RegQueryValueExW,
    (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD,
	    CONST BYTE*, DWORD)) RegSetValueExW,
};


/*
 * Declarations for functions defined in this file.
 */

static void		AppendSystemError(Tcl_Interp *interp, DWORD error);
static int		BroadcastValue(Tcl_Interp *interp, int objc,
			    Tcl_Obj * CONST objv[]);
static DWORD		ConvertDWORD(DWORD type, DWORD value);
static void		DeleteCmd(ClientData clientData);
static int		DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj);

static int		DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj);
static int		GetKeyNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *patternObj);
static int		GetType(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj);
static int		GetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj);
static int		GetValueNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *patternObj);
static int		OpenKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    REGSAM mode, int flags, HKEY *keyPtr);
static DWORD		OpenSubKey(char *hostName, HKEY rootKey,
			    char *keyName, REGSAM mode, int flags,
			    HKEY *keyPtr);
static int		ParseKeyName(Tcl_Interp *interp, char *name,
			    char **hostNamePtr, HKEY *rootKeyPtr,
			    char **keyNamePtr);
static DWORD		RecursiveDeleteKey(HKEY hStartKey,
			    CONST TCHAR * pKeyName);
static int		RegistryObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj * CONST objv[]);
static int		SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, Tcl_Obj *dataObj,
			    Tcl_Obj *typeObj);

































EXTERN int		Registry_Init(Tcl_Interp *interp);
EXTERN int		Registry_Unload(Tcl_Interp *interp, int flags);




/*
 *----------------------------------------------------------------------
 *
 * Registry_Init --
 *
 *	This function initializes the registry command.
180
181
182
183
184
185
186
187
188
189
190











191
192
193
194
195
196
197
198
199
200
201

int
Registry_Init(
    Tcl_Interp *interp)
{
    Tcl_Command cmd;

    if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
	return TCL_ERROR;
    }












    cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.3.5", NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *







|



>
>
>
>
>
>
>
>
>
>
>

|
|
|







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

int
Registry_Init(
    Tcl_Interp *interp)
{
    Tcl_Command cmd;

    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Determine if the unicode interfaces are available and select the
     * appropriate registry function table.
     */

    if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
	regWinProcs = &unicodeProcs;
    } else {
	regWinProcs = &asciiProcs;
    }

    cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd,
	(ClientData)interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, (ClientData)cmd);
    return Tcl_PkgProvide(interp, "registry", "1.2.2");
}

/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
int
Registry_Unload(
    Tcl_Interp *interp,		/* Interpreter for unloading */
    int flags)			/* Flags passed by the unload system */
{
    Tcl_Command cmd;
    Tcl_Obj *objv[3];
    (void)flags;

    /*
     * Unregister the registry package. There is no Tcl_PkgForget()
     */

    objv[0] = Tcl_NewStringObj("package", -1);
    objv[1] = Tcl_NewStringObj("forget", -1);







<







258
259
260
261
262
263
264

265
266
267
268
269
270
271
int
Registry_Unload(
    Tcl_Interp *interp,		/* Interpreter for unloading */
    int flags)			/* Flags passed by the unload system */
{
    Tcl_Command cmd;
    Tcl_Obj *objv[3];


    /*
     * Unregister the registry package. There is no Tcl_PkgForget()
     */

    objv[0] = Tcl_NewStringObj("package", -1);
    objv[1] = Tcl_NewStringObj("forget", -1);
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
 *	The unload command will not attempt to delete this command.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteCmd(
    void *clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;

    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * RegistryObjCmd --
 *
 *	This function implements the Tcl "registry" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
RegistryObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int n = 1;
    int index, argc;
    REGSAM mode = 0;
    const char *errString = NULL;

    static const char *const subcommands[] = {
	"broadcast", "delete", "get", "keys", "set", "type", "values", NULL
    };
    enum SubCmdIdx {
	BroadcastIdx, DeleteIdx, GetIdx, KeysIdx, SetIdx, TypeIdx, ValuesIdx
    };
    static const char *const modes[] = {
	"-32bit", "-64bit", NULL
    };
    (void)dummy;

    if (objc < 2) {
    wrongArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "?-32bit|-64bit? option ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetString(objv[n])[0] == '-') {
	if (Tcl_GetIndexFromObj(interp, objv[n++], modes, "mode", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (index) {
	case 0:			/* -32bit */
	    mode |= KEY_WOW64_32KEY;
	    break;
	case 1:			/* -64bit */
	    mode |= KEY_WOW64_64KEY;
	    break;
	}
	if (objc < 3) {
	    goto wrongArgs;
	}
    }

    if (Tcl_GetIndexFromObj(interp, objv[n++], subcommands, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    argc = (objc - n);
    switch (index) {
    case BroadcastIdx:		/* broadcast */
	if (argc == 1 || argc == 3) {
	    int res = BroadcastValue(interp, argc, objv + n);

	    if (res != TCL_BREAK) {
		return res;
	    }
	}
	errString = "keyName ?-timeout milliseconds?";
	break;
    case DeleteIdx:		/* delete */
	if (argc == 1) {
	    return DeleteKey(interp, objv[n], mode);
	} else if (argc == 2) {
	    return DeleteValue(interp, objv[n], objv[n+1], mode);
	}
	errString = "keyName ?valueName?";
	break;
    case GetIdx:		/* get */
	if (argc == 2) {
	    return GetValue(interp, objv[n], objv[n+1], mode);
	}
	errString = "keyName valueName";
	break;
    case KeysIdx:		/* keys */
	if (argc == 1) {
	    return GetKeyNames(interp, objv[n], NULL, mode);
	} else if (argc == 2) {
	    return GetKeyNames(interp, objv[n], objv[n+1], mode);
	}
	errString = "keyName ?pattern?";
	break;
    case SetIdx:		/* set */
	if (argc == 1) {
	    HKEY key;

	    /*
	     * Create the key and then close it immediately.
	     */

	    mode |= KEY_ALL_ACCESS;
	    if (OpenKey(interp, objv[n], mode, 1, &key) != TCL_OK) {
		return TCL_ERROR;
	    }
	    RegCloseKey(key);
	    return TCL_OK;
	} else if (argc == 3) {
	    return SetValue(interp, objv[n], objv[n+1], objv[n+2], NULL,
		    mode);
	} else if (argc == 4) {
	    return SetValue(interp, objv[n], objv[n+1], objv[n+2], objv[n+3],
		    mode);
	}
	errString = "keyName ?valueName data ?type??";
	break;
    case TypeIdx:		/* type */
	if (argc == 2) {
	    return GetType(interp, objv[n], objv[n+1], mode);
	}
	errString = "keyName valueName";
	break;
    case ValuesIdx:		/* values */
	if (argc == 1) {
	    return GetValueNames(interp, objv[n], NULL, mode);
	} else if (argc == 2) {
	    return GetValueNames(interp, objv[n], objv[n+1], mode);
	}
	errString = "keyName ?pattern?";
	break;
    }
    Tcl_WrongNumArgs(interp, (mode ? 3 : 2), objv, errString);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteKey --







|

|
<
|




















|


|

<
|
<
|

|





<
<
<
<


<
|



<
|
|
|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<


<
|
<
<
<
<
<
<


|
|
|
|




|
|




|
|
|
|




|






<
|




|
|
<
<
|
<




|
|




|
|
|
|




|







299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335

336
337
338
339
340
341
342
343




344
345

346
347
348
349

350
351
352
353







354











355
356

357






358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388

389
390
391
392
393
394
395


396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
 *	The unload command will not attempt to delete this command.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteCmd(
    ClientData clientData)
{
    Tcl_Interp *interp = clientData;

    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, (ClientData)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * RegistryObjCmd --
 *
 *	This function implements the Tcl "registry" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
RegistryObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj * CONST objv[])	/* Argument values. */
{

    int index;

    char *errString = NULL;

    static CONST char *subcommands[] = {
	"broadcast", "delete", "get", "keys", "set", "type", "values", NULL
    };
    enum SubCmdIdx {
	BroadcastIdx, DeleteIdx, GetIdx, KeysIdx, SetIdx, TypeIdx, ValuesIdx
    };





    if (objc < 2) {

	Tcl_WrongNumArgs(interp, objc, objv, "option ?arg arg ...?");
	return TCL_ERROR;
    }


    if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "option", 0, &index)
	    != TCL_OK) {
	return TCL_ERROR;
    }



















    switch (index) {
    case BroadcastIdx:		/* broadcast */

	return BroadcastValue(interp, objc, objv);






	break;
    case DeleteIdx:		/* delete */
	if (objc == 3) {
	    return DeleteKey(interp, objv[2]);
	} else if (objc == 4) {
	    return DeleteValue(interp, objv[2], objv[3]);
	}
	errString = "keyName ?valueName?";
	break;
    case GetIdx:		/* get */
	if (objc == 4) {
	    return GetValue(interp, objv[2], objv[3]);
	}
	errString = "keyName valueName";
	break;
    case KeysIdx:		/* keys */
	if (objc == 3) {
	    return GetKeyNames(interp, objv[2], NULL);
	} else if (objc == 4) {
	    return GetKeyNames(interp, objv[2], objv[3]);
	}
	errString = "keyName ?pattern?";
	break;
    case SetIdx:		/* set */
	if (objc == 3) {
	    HKEY key;

	    /*
	     * Create the key and then close it immediately.
	     */


	    if (OpenKey(interp, objv[2], KEY_ALL_ACCESS, 1, &key) != TCL_OK) {
		return TCL_ERROR;
	    }
	    RegCloseKey(key);
	    return TCL_OK;
	} else if (objc == 5 || objc == 6) {
	    Tcl_Obj *typeObj = (objc == 5) ? NULL : objv[5];


	    return SetValue(interp, objv[2], objv[3], objv[4], typeObj);

	}
	errString = "keyName ?valueName data ?type??";
	break;
    case TypeIdx:		/* type */
	if (objc == 4) {
	    return GetType(interp, objv[2], objv[3]);
	}
	errString = "keyName valueName";
	break;
    case ValuesIdx:		/* values */
	if (objc == 3) {
	    return GetValueNames(interp, objv[2], NULL);
	} else if (objc == 4) {
	    return GetValueNames(interp, objv[2], objv[3]);
	}
	errString = "keyName ?pattern?";
	break;
    }
    Tcl_WrongNumArgs(interp, 2, objv, errString);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteKey --
425
426
427
428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
 *
 *----------------------------------------------------------------------
 */

static int
DeleteKey(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key to delete. */
    REGSAM mode)		/* Mode flags to pass. */
{
    char *tail, *buffer, *hostName, *keyName;
    const WCHAR *nativeTail;
    HKEY rootKey, subkey;
    DWORD result;

    Tcl_DString buf;
    REGSAM saveMode = mode;

    /*
     * Find the parent of the key being deleted and open it.
     */

    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 1);
    strcpy(buffer, keyName);

    if (ParseKeyName(interp, buffer, &hostName, &rootKey,
	    &keyName) != TCL_OK) {
	Tcl_Free(buffer);
	return TCL_ERROR;
    }

    if (*keyName == '\0') {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("bad key: cannot delete root keys", -1));
	Tcl_SetErrorCode(interp, "WIN_REG", "DEL_ROOT_KEY", NULL);
	Tcl_Free(buffer);
	return TCL_ERROR;
    }

    tail = strrchr(keyName, '\\');
    if (tail) {
	*tail++ = '\0';
    } else {
	tail = keyName;
	keyName = NULL;
    }

    mode |= KEY_ENUMERATE_SUB_KEYS | DELETE;
    result = OpenSubKey(hostName, rootKey, keyName, mode, 0, &subkey);

    if (result != ERROR_SUCCESS) {
	Tcl_Free(buffer);
	if (result == ERROR_FILE_NOT_FOUND) {
	    return TCL_OK;
	}
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("unable to delete key: ", -1));
	AppendSystemError(interp, result);
	return TCL_ERROR;
    }

    /*
     * Now we recursively delete the key and everything below it.
     */

    Tcl_DStringInit(&buf);
    nativeTail = Tcl_UtfToWCharDString(tail, -1, &buf);
    result = RecursiveDeleteKey(subkey, nativeTail, saveMode);
    Tcl_DStringFree(&buf);

    if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("unable to delete key: ", -1));
	AppendSystemError(interp, result);
	result = TCL_ERROR;
    } else {
	result = TCL_OK;
    }

    RegCloseKey(subkey);
    Tcl_Free(buffer);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteValue --







|
<


|


>

<





|
|




|




|
|
<
|











<
|
>

|



|
|








<
|
|












|







431
432
433
434
435
436
437
438

439
440
441
442
443
444
445

446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
 *
 *----------------------------------------------------------------------
 */

static int
DeleteKey(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj)	/* Name of key to delete. */

{
    char *tail, *buffer, *hostName, *keyName;
    CONST char *nativeTail;
    HKEY rootKey, subkey;
    DWORD result;
    int length;
    Tcl_DString buf;


    /*
     * Find the parent of the key being deleted and open it.
     */

    keyName = Tcl_GetStringFromObj(keyNameObj, &length);
    buffer = ckalloc((unsigned int) length + 1);
    strcpy(buffer, keyName);

    if (ParseKeyName(interp, buffer, &hostName, &rootKey,
	    &keyName) != TCL_OK) {
	ckfree(buffer);
	return TCL_ERROR;
    }

    if (*keyName == '\0') {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"bad key: cannot delete root keys", -1));

	ckfree(buffer);
	return TCL_ERROR;
    }

    tail = strrchr(keyName, '\\');
    if (tail) {
	*tail++ = '\0';
    } else {
	tail = keyName;
	keyName = NULL;
    }


    result = OpenSubKey(hostName, rootKey, keyName,
	    KEY_ENUMERATE_SUB_KEYS | DELETE, 0, &subkey);
    if (result != ERROR_SUCCESS) {
	ckfree(buffer);
	if (result == ERROR_FILE_NOT_FOUND) {
	    return TCL_OK;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"unable to delete key: ", -1));
	AppendSystemError(interp, result);
	return TCL_ERROR;
    }

    /*
     * Now we recursively delete the key and everything below it.
     */


    nativeTail = Tcl_WinUtfToTChar(tail, -1, &buf);
    result = RecursiveDeleteKey(subkey, nativeTail);
    Tcl_DStringFree(&buf);

    if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("unable to delete key: ", -1));
	AppendSystemError(interp, result);
	result = TCL_ERROR;
    } else {
	result = TCL_OK;
    }

    RegCloseKey(subkey);
    ckfree(buffer);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteValue --
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
 *----------------------------------------------------------------------
 */

static int
DeleteValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj,	/* Name of value to delete. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    char *valueName;

    DWORD result;
    Tcl_DString ds;

    /*
     * Attempt to open the key for deletion.
     */

    mode |= KEY_SET_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {

	return TCL_ERROR;
    }

    valueName = Tcl_GetString(valueNameObj);
    Tcl_DStringInit(&ds);
    Tcl_UtfToWCharDString(valueName, valueNameObj->length, &ds);
    result = RegDeleteValueW(key, (const WCHAR *)Tcl_DStringValue(&ds));
    Tcl_DStringFree(&ds);
    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to delete value \"%s\" from key \"%s\": ",
		Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj)));

	AppendSystemError(interp, result);
	result = TCL_ERROR;
    } else {
	result = TCL_OK;
    }
    RegCloseKey(key);
    return result;







|
<



>







<
|
>



|
<
|
|


<
|
|
>







524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542

543
544
545
546
547
548

549
550
551
552

553
554
555
556
557
558
559
560
561
562
 *----------------------------------------------------------------------
 */

static int
DeleteValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj)	/* Name of value to delete. */

{
    HKEY key;
    char *valueName;
    int length;
    DWORD result;
    Tcl_DString ds;

    /*
     * Attempt to open the key for deletion.
     */


    if (OpenKey(interp, keyNameObj, KEY_SET_VALUE, 0, &key)
	    != TCL_OK) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetStringFromObj(valueNameObj, &length);

    Tcl_WinUtfToTChar(valueName, length, &ds);
    result = (*regWinProcs->regDeleteValueProc)(key, Tcl_DStringValue(&ds));
    Tcl_DStringFree(&ds);
    if (result != ERROR_SUCCESS) {

	Tcl_AppendResult(interp, "unable to delete value \"",
		Tcl_GetString(valueNameObj), "\" from key \"",
		Tcl_GetString(keyNameObj), "\": ", NULL);
	AppendSystemError(interp, result);
	result = TCL_ERROR;
    } else {
	result = TCL_OK;
    }
    RegCloseKey(key);
    return result;
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636


637


638
639
640
641
642
643
644
 *----------------------------------------------------------------------
 */

static int
GetKeyNames(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to enumerate. */
    Tcl_Obj *patternObj,	/* Optional match pattern. */
    REGSAM mode)		/* Mode flags to pass. */
{
    const char *pattern;	/* Pattern being matched against subkeys */
    HKEY key;			/* Handle to the key being examined */
    WCHAR buffer[MAX_KEY_LENGTH];
				/* Buffer to hold the subkey name */
    DWORD bufSize;		/* Size of the buffer */
    DWORD index;		/* Position of the current subkey */
    char *name;			/* Subkey name */
    Tcl_Obj *resultPtr;		/* List of subkeys being accumulated */
    int result = TCL_OK;	/* Return value from this command */
    Tcl_DString ds;		/* Buffer to translate subkey name to UTF-8 */

    if (patternObj) {
	pattern = Tcl_GetString(patternObj);
    } else {
	pattern = NULL;
    }

    /*
     * Attempt to open the key for enumeration.
     */


    mode |= KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Enumerate the subkeys.
     */

    resultPtr = Tcl_NewObj();
    for (index = 0;; ++index) {
	bufSize = MAX_KEY_LENGTH;
	result = RegEnumKeyExW(key, index, buffer, &bufSize,
		NULL, NULL, NULL, NULL);
	if (result != ERROR_SUCCESS) {
	    if (result == ERROR_NO_MORE_ITEMS) {
		result = TCL_OK;
	    } else {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(

			"unable to enumerate subkeys of \"%s\": ",
			Tcl_GetString(keyNameObj)));
		AppendSystemError(interp, result);
		result = TCL_ERROR;
	    }
	    break;
	}
	Tcl_DStringInit(&ds);


	name = Tcl_WCharToUtfDString(buffer, bufSize, &ds);


	if (pattern && !Tcl_StringMatch(name, pattern)) {
	    Tcl_DStringFree(&ds);
	    continue;
	}
	result = Tcl_ListObjAppendElement(interp, resultPtr,
		Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
	Tcl_DStringFree(&ds);







|
<

|

<
|













<
|
<

>
|
|



<
|
<




|
|




|
>
|
|





|
>
>
|
>
>







581
582
583
584
585
586
587
588

589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605

606

607
608
609
610
611
612
613

614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
 *----------------------------------------------------------------------
 */

static int
GetKeyNames(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to enumerate. */
    Tcl_Obj *patternObj)	/* Optional match pattern. */

{
    char *pattern;		/* Pattern being matched against subkeys */
    HKEY key;			/* Handle to the key being examined */

    TCHAR buffer[MAX_KEY_LENGTH*2];		/* Buffer to hold the subkey name */
    DWORD bufSize;		/* Size of the buffer */
    DWORD index;		/* Position of the current subkey */
    char *name;			/* Subkey name */
    Tcl_Obj *resultPtr;		/* List of subkeys being accumulated */
    int result = TCL_OK;	/* Return value from this command */
    Tcl_DString ds;		/* Buffer to translate subkey name to UTF-8 */

    if (patternObj) {
	pattern = Tcl_GetString(patternObj);
    } else {
	pattern = NULL;
    }


    /* Attempt to open the key for enumeration. */


    if (OpenKey(interp, keyNameObj,
		KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
		0, &key) != TCL_OK) {
	return TCL_ERROR;
    }


    /* Enumerate the subkeys */


    resultPtr = Tcl_NewObj();
    for (index = 0;; ++index) {
	bufSize = MAX_KEY_LENGTH;
	result = (*regWinProcs->regEnumKeyExProc)
	    (key, index, buffer, &bufSize, NULL, NULL, NULL, NULL);
	if (result != ERROR_SUCCESS) {
	    if (result == ERROR_NO_MORE_ITEMS) {
		result = TCL_OK;
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewObj());
		Tcl_AppendResult(interp,
			"unable to enumerate subkeys of \"",
			Tcl_GetString(keyNameObj), "\": ", NULL);
		AppendSystemError(interp, result);
		result = TCL_ERROR;
	    }
	    break;
	}
	if (regWinProcs->useWide) {
	    Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize * sizeof(WCHAR), &ds);
	} else {
	    Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize, &ds);
	}
	name = Tcl_DStringValue(&ds);
	if (pattern && !Tcl_StringMatch(name, pattern)) {
	    Tcl_DStringFree(&ds);
	    continue;
	}
	result = Tcl_ListObjAppendElement(interp, resultPtr,
		Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
	Tcl_DStringFree(&ds);
673
674
675
676
677
678
679
680
681
682
683
684

685
686
687

688
689
690
691
692
693
694

695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

714
715
716
717
718
719
720
 *----------------------------------------------------------------------
 */

static int
GetType(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj,	/* Name of value to get. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    DWORD result, type;

    Tcl_DString ds;
    const char *valueName;
    const WCHAR *nativeValue;


    /*
     * Attempt to open the key for reading.
     */

    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {

	return TCL_ERROR;
    }

    /*
     * Get the type of the value.
     */

    valueName = Tcl_GetString(valueNameObj);
    Tcl_DStringInit(&ds);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &ds);
    result = RegQueryValueExW(key, nativeValue, NULL, &type,
	    NULL, NULL);
    Tcl_DStringFree(&ds);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to get type of value \"%s\" from key \"%s\": ",
		Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj)));

	AppendSystemError(interp, result);
	return TCL_ERROR;
    }

    /*
     * Set the type into the result. Watch out for unknown types. If we don't
     * know about the type, just use the numeric value.







|
<


|
>

|
|
>





<
|
>







|
<
|
|





<
|
|
>







675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712

713
714
715
716
717
718
719
720
721
722
 *----------------------------------------------------------------------
 */

static int
GetType(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj)	/* Name of value to get. */

{
    HKEY key;
    DWORD result;
    DWORD type;
    Tcl_DString ds;
    char *valueName;
    CONST char *nativeValue;
    int length;

    /*
     * Attempt to open the key for reading.
     */


    if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key)
	    != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Get the type of the value.
     */

    valueName = Tcl_GetStringFromObj(valueNameObj, &length);

    nativeValue = Tcl_WinUtfToTChar(valueName, length, &ds);
    result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type,
	    NULL, NULL);
    Tcl_DStringFree(&ds);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {

	Tcl_AppendResult(interp, "unable to get type of value \"",
		Tcl_GetString(valueNameObj), "\" from key \"",
		Tcl_GetString(keyNameObj), "\": ", NULL);
	AppendSystemError(interp, result);
	return TCL_ERROR;
    }

    /*
     * Set the type into the result. Watch out for unknown types. If we don't
     * know about the type, just use the numeric value.
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842

843
844



845
846
847
848
849
850
851
852
853
854
855
856
857
858
 *----------------------------------------------------------------------
 */

static int
GetValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj,	/* Name of value to get. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    const char *valueName;
    const WCHAR *nativeValue;
    DWORD result, length, type;
    Tcl_DString data, buf;


    /*
     * Attempt to open the key for reading.
     */

    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Initialize a Dstring to maximum statically allocated size we could get
     * one more byte by avoiding Tcl_DStringSetLength() and just setting
     * length to TCL_DSTRING_STATIC_SIZE, but this should be safer if the
     * implementation of Dstrings changes.
     *
     * This allows short values to be read from the registy in one call.
     * Longer values need a second call with an expanded DString.
     */

    Tcl_DStringInit(&data);
    Tcl_DStringSetLength(&data, TCL_DSTRING_STATIC_SIZE - 1);
    length = TCL_DSTRING_STATIC_SIZE/sizeof(WCHAR) - 1;

    valueName = Tcl_GetString(valueNameObj);
    Tcl_DStringInit(&buf);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &buf);

    result = RegQueryValueExW(key, nativeValue, NULL, &type,
	    (BYTE *) Tcl_DStringValue(&data), &length);
    while (result == ERROR_MORE_DATA) {
	/*
	 * The Windows docs say that in this error case, we just need to
	 * expand our buffer and request more data. Required for
	 * HKEY_PERFORMANCE_DATA
	 */

	length = Tcl_DStringLength(&data) * (2 / sizeof(WCHAR));
	Tcl_DStringSetLength(&data, (int) length * sizeof(WCHAR));
	result = RegQueryValueExW(key, nativeValue,
		NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length);
    }
    Tcl_DStringFree(&buf);
    RegCloseKey(key);
    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to get value \"%s\" from key \"%s\": ",
		Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj)));

	AppendSystemError(interp, result);
	Tcl_DStringFree(&data);
	return TCL_ERROR;
    }

    /*
     * If the data is a 32-bit quantity, store it as an integer object. If it
     * is a multi-string, store it as a list of strings. For null-terminated
     * strings, append up the to first null. Otherwise, store it as a binary
     * string.
     */

    if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj((int) ConvertDWORD(type,
		*((DWORD *) Tcl_DStringValue(&data)))));
    } else if (type == REG_MULTI_SZ) {
	char *p = Tcl_DStringValue(&data);
	char *end = Tcl_DStringValue(&data) + length;
	Tcl_Obj *resultPtr = Tcl_NewObj();

	/*
	 * Multistrings are stored as an array of null-terminated strings,
	 * terminated by two null characters. Also do a bounds check in case
	 * we get bogus data.
	 */

	while ((p < end) && *((WCHAR *) p) != 0) {
	    WCHAR *wp = (WCHAR *) p;

	    Tcl_DStringInit(&buf);
	    Tcl_WCharToUtfDString(wp, wcslen(wp), &buf);
	    Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(Tcl_DStringValue(&buf),
			    Tcl_DStringLength(&buf)));


	    while (*wp++ != 0) {/* empty body */}
	    p = (char *) wp;



	    Tcl_DStringFree(&buf);
	}
	Tcl_SetObjResult(interp, resultPtr);
    } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
	WCHAR *wp = (WCHAR *) Tcl_DStringValue(&data);
	Tcl_DStringInit(&buf);
	Tcl_WCharToUtfDString((const WCHAR *)Tcl_DStringValue(&data), wcslen(wp), &buf);
	Tcl_DStringResult(interp, &buf);
    } else {
	/*
	 * Save binary data as a byte array.
	 */

	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(







|
<


|
|


>





<
|















|

|
<
|

|








|
|
|





<
|
|
>














|











|
<
|
<
|



|
>
|
|
>
>
>




|
<
<







747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834

835

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851


852
853
854
855
856
857
858
 *----------------------------------------------------------------------
 */

static int
GetValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj)	/* Name of value to get. */

{
    HKEY key;
    char *valueName;
    CONST char *nativeValue;
    DWORD result, length, type;
    Tcl_DString data, buf;
    int nameLen;

    /*
     * Attempt to open the key for reading.
     */


    if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Initialize a Dstring to maximum statically allocated size we could get
     * one more byte by avoiding Tcl_DStringSetLength() and just setting
     * length to TCL_DSTRING_STATIC_SIZE, but this should be safer if the
     * implementation of Dstrings changes.
     *
     * This allows short values to be read from the registy in one call.
     * Longer values need a second call with an expanded DString.
     */

    Tcl_DStringInit(&data);
    Tcl_DStringSetLength(&data, TCL_DSTRING_STATIC_SIZE - 1);
    length = TCL_DSTRING_STATIC_SIZE / (regWinProcs->useWide ? 2 : 1) - 1;

    valueName = Tcl_GetStringFromObj(valueNameObj, &nameLen);

    nativeValue = Tcl_WinUtfToTChar(valueName, nameLen, &buf);

    result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type,
	    (BYTE *) Tcl_DStringValue(&data), &length);
    while (result == ERROR_MORE_DATA) {
	/*
	 * The Windows docs say that in this error case, we just need to
	 * expand our buffer and request more data. Required for
	 * HKEY_PERFORMANCE_DATA
	 */

	length = Tcl_DStringLength(&data) * (regWinProcs->useWide ? 1 : 2);
	Tcl_DStringSetLength(&data, (int) length * (regWinProcs->useWide ? 2 : 1));
	result = (*regWinProcs->regQueryValueExProc)(key, (char *) nativeValue,
		NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length);
    }
    Tcl_DStringFree(&buf);
    RegCloseKey(key);
    if (result != ERROR_SUCCESS) {

	Tcl_AppendResult(interp, "unable to get value \"",
		Tcl_GetString(valueNameObj), "\" from key \"",
		Tcl_GetString(keyNameObj), "\": ", NULL);
	AppendSystemError(interp, result);
	Tcl_DStringFree(&data);
	return TCL_ERROR;
    }

    /*
     * If the data is a 32-bit quantity, store it as an integer object. If it
     * is a multi-string, store it as a list of strings. For null-terminated
     * strings, append up the to first null. Otherwise, store it as a binary
     * string.
     */

    if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
	Tcl_SetObjResult(interp, Tcl_NewIntObj((int) ConvertDWORD(type,
		*((DWORD*) Tcl_DStringValue(&data)))));
    } else if (type == REG_MULTI_SZ) {
	char *p = Tcl_DStringValue(&data);
	char *end = Tcl_DStringValue(&data) + length;
	Tcl_Obj *resultPtr = Tcl_NewObj();

	/*
	 * Multistrings are stored as an array of null-terminated strings,
	 * terminated by two null characters. Also do a bounds check in case
	 * we get bogus data.
	 */

	while (p < end 	&& ((regWinProcs->useWide)

		? *((Tcl_UniChar *)p) : *p) != 0) {

	    Tcl_WinTCharToUtf((TCHAR *) p, -1, &buf);
	    Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(Tcl_DStringValue(&buf),
			    Tcl_DStringLength(&buf)));
	    if (regWinProcs->useWide) {
		Tcl_UniChar* up = (Tcl_UniChar*) p;
		while (*up++ != 0) {}
		p = (char*) up;
	    } else {
		while (*p++ != '\0') {}
	    }
	    Tcl_DStringFree(&buf);
	}
	Tcl_SetObjResult(interp, resultPtr);
    } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
	Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&data), -1, &buf);


	Tcl_DStringResult(interp, &buf);
    } else {
	/*
	 * Save binary data as a byte array.
	 */

	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

925
926
927



928
929

930
931
932
933
934
935
936
 *----------------------------------------------------------------------
 */

static int
GetValueNames(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to enumerate. */
    Tcl_Obj *patternObj,	/* Optional match pattern. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    Tcl_Obj *resultPtr;
    DWORD index, size, result;
    Tcl_DString buffer, ds;
    const char *pattern, *name;

    /*
     * Attempt to open the key for enumeration.
     */

    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {

	return TCL_ERROR;
    }

    resultPtr = Tcl_NewObj();
    Tcl_DStringInit(&buffer);
    Tcl_DStringSetLength(&buffer, (int) (MAX_KEY_LENGTH * sizeof(WCHAR)));

    index = 0;
    result = TCL_OK;

    if (patternObj) {
	pattern = Tcl_GetString(patternObj);
    } else {
	pattern = NULL;
    }

    /*
     * Enumerate the values under the given subkey until we get an error,
     * indicating the end of the list. Note that we need to reset size after
     * each iteration because RegEnumValue smashes the old value.
     */

    size = MAX_KEY_LENGTH;

    while (RegEnumValueW(key,index, (WCHAR *)Tcl_DStringValue(&buffer),
	    &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {




	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString((const WCHAR *)Tcl_DStringValue(&buffer), size, &ds);

	name = Tcl_DStringValue(&ds);
	if (!pattern || Tcl_StringMatch(name, pattern)) {
	    result = Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
	    if (result != TCL_OK) {
		Tcl_DStringFree(&ds);
		break;







|
<





|





<
|
>





|
>
















>
|
|

>
>
>
|
|
>







881
882
883
884
885
886
887
888

889
890
891
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
 *----------------------------------------------------------------------
 */

static int
GetValueNames(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to enumerate. */
    Tcl_Obj *patternObj)	/* Optional match pattern. */

{
    HKEY key;
    Tcl_Obj *resultPtr;
    DWORD index, size, result;
    Tcl_DString buffer, ds;
    char *pattern, *name;

    /*
     * Attempt to open the key for enumeration.
     */


    if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key)
	    != TCL_OK) {
	return TCL_ERROR;
    }

    resultPtr = Tcl_NewObj();
    Tcl_DStringInit(&buffer);
    Tcl_DStringSetLength(&buffer,
	    (int) ((regWinProcs->useWide) ? MAX_KEY_LENGTH*2 : MAX_KEY_LENGTH));
    index = 0;
    result = TCL_OK;

    if (patternObj) {
	pattern = Tcl_GetString(patternObj);
    } else {
	pattern = NULL;
    }

    /*
     * Enumerate the values under the given subkey until we get an error,
     * indicating the end of the list. Note that we need to reset size after
     * each iteration because RegEnumValue smashes the old value.
     */

    size = MAX_KEY_LENGTH;
    while ((*regWinProcs->regEnumValueProc)(key, index,
	    Tcl_DStringValue(&buffer), &size, NULL, NULL, NULL, NULL)
	    == ERROR_SUCCESS) {

	if (regWinProcs->useWide) {
	    size *= 2;
	}

	Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&buffer), (int) size,
		&ds);
	name = Tcl_DStringValue(&ds);
	if (!pattern || Tcl_StringMatch(name, pattern)) {
	    result = Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
	    if (result != TCL_OK) {
		Tcl_DStringFree(&ds);
		break;
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to open. */
    REGSAM mode,		/* Access mode. */
    int flags,			/* 0 or REG_CREATE. */
    HKEY *keyPtr)		/* Returned HKEY. */
{
    char *keyName, *buffer, *hostName;

    HKEY rootKey;
    DWORD result;

    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 1);
    strcpy(buffer, keyName);

    result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName);
    if (result == TCL_OK) {
	result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr);
	if (result != ERROR_SUCCESS) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("unable to open key: ", -1));
	    AppendSystemError(interp, result);
	    result = TCL_ERROR;
	} else {
	    result = TCL_OK;
	}
    }

    Tcl_Free(buffer);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * OpenSubKey --







>



|
|















|







974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Key to open. */
    REGSAM mode,		/* Access mode. */
    int flags,			/* 0 or REG_CREATE. */
    HKEY *keyPtr)		/* Returned HKEY. */
{
    char *keyName, *buffer, *hostName;
    int length;
    HKEY rootKey;
    DWORD result;

    keyName = Tcl_GetStringFromObj(keyNameObj, &length);
    buffer = ckalloc((unsigned int) length + 1);
    strcpy(buffer, keyName);

    result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName);
    if (result == TCL_OK) {
	result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr);
	if (result != ERROR_SUCCESS) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("unable to open key: ", -1));
	    AppendSystemError(interp, result);
	    result = TCL_ERROR;
	} else {
	    result = TCL_OK;
	}
    }

    ckfree(buffer);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * OpenSubKey --
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
    Tcl_DString buf;

    /*
     * Attempt to open the root key on a remote host if necessary.
     */

    if (hostName) {
	Tcl_DStringInit(&buf);
	hostName = (char *) Tcl_UtfToWCharDString(hostName, -1, &buf);
	result = RegConnectRegistryW((WCHAR *)hostName, rootKey,
		&rootKey);
	Tcl_DStringFree(&buf);
	if (result != ERROR_SUCCESS) {
	    return result;
	}
    }

    /*
     * Now open the specified key with the requested permissions. Note that
     * this key must be closed by the caller.
     */

    if (keyName) {
	Tcl_DStringInit(&buf);
	keyName = (char *) Tcl_UtfToWCharDString(keyName, -1, &buf);
    }
    if (flags & REG_CREATE) {
	DWORD create;

	result = RegCreateKeyExW(rootKey, (WCHAR *)keyName, 0, NULL,
		REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create);
    } else if (rootKey == HKEY_PERFORMANCE_DATA) {
	/*
	 * Here we fudge it for this special root key. See MSDN for more info
	 * on HKEY_PERFORMANCE_DATA and the peculiarities surrounding it.
	 */

	*keyPtr = HKEY_PERFORMANCE_DATA;
	result = ERROR_SUCCESS;
    } else {
	result = RegOpenKeyExW(rootKey, (WCHAR *)keyName, 0, mode,
		keyPtr);
    }
    if (keyName) {
	Tcl_DStringFree(&buf);
    }

    /*
     * Be sure to close the root key since we are done with it now.
     */

    if (hostName) {
	RegCloseKey(rootKey);







<
|
|












<
<
|
<


|
<






<



|


<
|
<







1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054


1055

1056
1057
1058

1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070

1071

1072
1073
1074
1075
1076
1077
1078
    Tcl_DString buf;

    /*
     * Attempt to open the root key on a remote host if necessary.
     */

    if (hostName) {

	hostName = (char *) Tcl_WinUtfToTChar(hostName, -1, &buf);
	result = (*regWinProcs->regConnectRegistryProc)(hostName, rootKey,
		&rootKey);
	Tcl_DStringFree(&buf);
	if (result != ERROR_SUCCESS) {
	    return result;
	}
    }

    /*
     * Now open the specified key with the requested permissions. Note that
     * this key must be closed by the caller.
     */



    keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf);

    if (flags & REG_CREATE) {
	DWORD create;
	result = (*regWinProcs->regCreateKeyExProc)(rootKey, keyName, 0, NULL,

		REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create);
    } else if (rootKey == HKEY_PERFORMANCE_DATA) {
	/*
	 * Here we fudge it for this special root key. See MSDN for more info
	 * on HKEY_PERFORMANCE_DATA and the peculiarities surrounding it.
	 */

	*keyPtr = HKEY_PERFORMANCE_DATA;
	result = ERROR_SUCCESS;
    } else {
	result = (*regWinProcs->regOpenKeyExProc)(rootKey, keyName, 0, mode,
		keyPtr);
    }

    Tcl_DStringFree(&buf);


    /*
     * Be sure to close the root key since we are done with it now.
     */

    if (hostName) {
	RegCloseKey(rootKey);
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
		}
	    }
	}
    } else {
	rootName = name;
    }
    if (!rootName) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad key \"%s\": must start with a valid root", name));
	Tcl_SetErrorCode(interp, "WIN_REG", "NO_ROOT_KEY", NULL);
	return TCL_ERROR;
    }

    /*
     * Split the root into root and subkey portions.
     */








|
|
<







1125
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
		}
	    }
	}
    } else {
	rootName = name;
    }
    if (!rootName) {
	Tcl_AppendResult(interp, "bad key \"", name,
		"\": must start with a valid root", NULL);

	return TCL_ERROR;
    }

    /*
     * Split the root into root and subkey portions.
     */

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
 *
 *----------------------------------------------------------------------
 */

static DWORD
RecursiveDeleteKey(
    HKEY startKey,		/* Parent of key to be deleted. */
    const WCHAR *keyName,	/* Name of key to be deleted in external
				 * encoding, not UTF. */
    REGSAM mode)		/* Mode flags to pass. */
{
    DWORD result, size;
    Tcl_DString subkey;
    HKEY hKey;
    REGSAM saveMode = mode;
    static int checkExProc = 0;
    static LONG (* regDeleteKeyExProc) (HKEY, LPCWSTR, REGSAM, DWORD) = (LONG (*) (HKEY, LPCWSTR, REGSAM, DWORD)) NULL;

    /*
     * Do not allow NULL or empty key name.
     */

    if (!keyName || *keyName == '\0') {
	return ERROR_BADKEY;
    }


    mode |= KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE;
    result = RegOpenKeyExW(startKey, keyName, 0, mode, &hKey);
    if (result != ERROR_SUCCESS) {
	return result;
    }

    Tcl_DStringInit(&subkey);
    Tcl_DStringSetLength(&subkey, (int) (MAX_KEY_LENGTH * sizeof(WCHAR)));


    mode = saveMode;
    while (result == ERROR_SUCCESS) {
	/*
	 * Always get index 0 because key deletion changes ordering.
	 */

	size = MAX_KEY_LENGTH;
	result = RegEnumKeyExW(hKey, 0, (WCHAR *)Tcl_DStringValue(&subkey),
		&size, NULL, NULL, NULL, NULL);
	if (result == ERROR_NO_MORE_ITEMS) {
	    /*
	     * RegDeleteKeyEx doesn't exist on non-64bit XP platforms, so we
	     * can't compile with it in. We need to check for it at runtime
	     * and use it if we find it.
	     */

	    if (mode && !checkExProc) {
		HMODULE handle;

		checkExProc = 1;
		handle = GetModuleHandleW(L"ADVAPI32");
		regDeleteKeyExProc = (LONG (*) (HKEY, LPCWSTR, REGSAM, DWORD))
			(void *)GetProcAddress(handle, "RegDeleteKeyExW");
	    }
	    if (mode && regDeleteKeyExProc) {
		result = regDeleteKeyExProc(startKey, keyName, mode, 0);
	    } else {
		result = RegDeleteKeyW(startKey, keyName);
	    }
	    break;
	} else if (result == ERROR_SUCCESS) {
	    result = RecursiveDeleteKey(hKey,
		    (const WCHAR *) Tcl_DStringValue(&subkey), mode);
	}
    }
    Tcl_DStringFree(&subkey);
    RegCloseKey(hKey);
    return result;
}








|

<




<
<
<









>
|
<





|
>

<






|
|

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<


|
<







1178
1179
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190



1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218





1219













1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
 *
 *----------------------------------------------------------------------
 */

static DWORD
RecursiveDeleteKey(
    HKEY startKey,		/* Parent of key to be deleted. */
    CONST char *keyName)	/* Name of key to be deleted in external
				 * encoding, not UTF. */

{
    DWORD result, size;
    Tcl_DString subkey;
    HKEY hKey;




    /*
     * Do not allow NULL or empty key name.
     */

    if (!keyName || *keyName == '\0') {
	return ERROR_BADKEY;
    }

    result = (*regWinProcs->regOpenKeyExProc)(startKey, keyName, 0,
	    KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE, &hKey);

    if (result != ERROR_SUCCESS) {
	return result;
    }

    Tcl_DStringInit(&subkey);
    Tcl_DStringSetLength(&subkey,
	    (int) ((regWinProcs->useWide) ? MAX_KEY_LENGTH * 2 : MAX_KEY_LENGTH));


    while (result == ERROR_SUCCESS) {
	/*
	 * Always get index 0 because key deletion changes ordering.
	 */

	size = MAX_KEY_LENGTH;
	result=(*regWinProcs->regEnumKeyExProc)(hKey, 0,
		Tcl_DStringValue(&subkey), &size, NULL, NULL, NULL, NULL);
	if (result == ERROR_NO_MORE_ITEMS) {





	    result = (*regWinProcs->regDeleteKeyProc)(startKey, keyName);













	    break;
	} else if (result == ERROR_SUCCESS) {
	    result = RecursiveDeleteKey(hKey, Tcl_DStringValue(&subkey));

	}
    }
    Tcl_DStringFree(&subkey);
    RegCloseKey(hKey);
    return result;
}

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343



1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369

1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390

static int
SetValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj,	/* Name of value to set. */
    Tcl_Obj *dataObj,		/* Data to be written. */
    Tcl_Obj *typeObj,		/* Type of data to be written. */
    REGSAM mode)		/* Mode flags to pass. */
{
    int type;
    DWORD result;
    HKEY key;

    const char *valueName;
    Tcl_DString nameBuf;

    if (typeObj == NULL) {
	type = REG_SZ;
    } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type",
	    0, (int *) &type) != TCL_OK) {
	if (Tcl_GetIntFromObj(NULL, typeObj, (int *) &type) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
    }
    mode |= KEY_ALL_ACCESS;
    if (OpenKey(interp, keyNameObj, mode, 1, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetString(valueNameObj);
    Tcl_DStringInit(&nameBuf);
    valueName = (char *) Tcl_UtfToWCharDString(valueName, valueNameObj->length, &nameBuf);

    if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
	int value;

	if (Tcl_GetIntFromObj(interp, dataObj, &value) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	value = ConvertDWORD((DWORD) type, (DWORD) value);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, (BYTE *) &value, sizeof(DWORD));
    } else if (type == REG_MULTI_SZ) {
	Tcl_DString data, buf;
	int objc, i;
	Tcl_Obj **objv;

	if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	/*
	 * Append the elements as null terminated strings. Note that we must
	 * not assume the length of the string in case there are embedded
	 * nulls, which aren't allowed in REG_MULTI_SZ values.
	 */

	Tcl_DStringInit(&data);
	for (i = 0; i < objc; i++) {
	    const char *bytes = Tcl_GetString(objv[i]);

	    Tcl_DStringAppend(&data, bytes, objv[i]->length);

	    /*
	     * Add a null character to separate this value from the next.



	     */

	    Tcl_DStringAppend(&data, "", 1);	/* NUL-terminated string */
	}

	Tcl_DStringInit(&buf);
	Tcl_UtfToWCharDString(Tcl_DStringValue(&data), Tcl_DStringLength(&data)+1,
		&buf);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, (BYTE *) Tcl_DStringValue(&buf),
		(DWORD) Tcl_DStringLength(&buf));
	Tcl_DStringFree(&data);
	Tcl_DStringFree(&buf);
    } else if (type == REG_SZ || type == REG_EXPAND_SZ) {
	Tcl_DString buf;
	const char *data = Tcl_GetString(dataObj);

	Tcl_DStringInit(&buf);
	data = (char *) Tcl_UtfToWCharDString(data, dataObj->length, &buf);

	/*
	 * Include the null in the length, padding if needed for WCHAR.
	 */


	Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf)+1);


	result = RegSetValueExW(key, (WCHAR *) valueName, 0,

		(DWORD) type, (BYTE *) data, (DWORD) Tcl_DStringLength(&buf) + 1);
	Tcl_DStringFree(&buf);
    } else {
	BYTE *data;
	size_t bytelength;

	/*
	 * Store binary data in the registry.
	 */

	data = (BYTE *) getByteArrayFromObj(dataObj, &bytelength);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, data, (DWORD) bytelength);
    }

    Tcl_DStringFree(&nameBuf);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp,







|
<




>
|






|




<
|



|
<
|










|
|




















<
<
|


|
>
>
>


|


<
|

|
|





|

<
|


|


>
|
|
>
|
>
|



<





|
|
|







1247
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309


1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363

static int
SetValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *keyNameObj,	/* Name of key. */
    Tcl_Obj *valueNameObj,	/* Name of value to set. */
    Tcl_Obj *dataObj,		/* Data to be written. */
    Tcl_Obj *typeObj)		/* Type of data to be written. */

{
    int type;
    DWORD result;
    HKEY key;
    int length;
    char *valueName;
    Tcl_DString nameBuf;

    if (typeObj == NULL) {
	type = REG_SZ;
    } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type",
	    0, (int *) &type) != TCL_OK) {
	if (Tcl_GetIntFromObj(NULL, typeObj, (int*) &type) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
    }

    if (OpenKey(interp, keyNameObj, KEY_ALL_ACCESS, 1, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetStringFromObj(valueNameObj, &length);

    valueName = (char *) Tcl_WinUtfToTChar(valueName, length, &nameBuf);

    if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
	int value;

	if (Tcl_GetIntFromObj(interp, dataObj, &value) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	value = ConvertDWORD((DWORD)type, (DWORD)value);
	result = (*regWinProcs->regSetValueExProc)(key, valueName, 0,
		(DWORD) type, (BYTE *) &value, sizeof(DWORD));
    } else if (type == REG_MULTI_SZ) {
	Tcl_DString data, buf;
	int objc, i;
	Tcl_Obj **objv;

	if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	/*
	 * Append the elements as null terminated strings. Note that we must
	 * not assume the length of the string in case there are embedded
	 * nulls, which aren't allowed in REG_MULTI_SZ values.
	 */

	Tcl_DStringInit(&data);
	for (i = 0; i < objc; i++) {


	    Tcl_DStringAppend(&data, Tcl_GetString(objv[i]), -1);

	    /*
	     * Add a null character to separate this value from the next. We
	     * accomplish this by growing the string by one byte. Since the
	     * DString always tacks on an extra null byte, the new byte will
	     * already be set to null.
	     */

	    Tcl_DStringSetLength(&data, Tcl_DStringLength(&data)+1);
	}


	Tcl_WinUtfToTChar(Tcl_DStringValue(&data), Tcl_DStringLength(&data)+1,
		&buf);
	result = (*regWinProcs->regSetValueExProc)(key, valueName, 0,
                (DWORD) type, (BYTE *) Tcl_DStringValue(&buf),
		(DWORD) Tcl_DStringLength(&buf));
	Tcl_DStringFree(&data);
	Tcl_DStringFree(&buf);
    } else if (type == REG_SZ || type == REG_EXPAND_SZ) {
	Tcl_DString buf;
	CONST char *data = Tcl_GetStringFromObj(dataObj, &length);


	data = Tcl_WinUtfToTChar(data, length, &buf);

	/*
	 * Include the null in the length, padding if needed for Unicode.
	 */

	if (regWinProcs->useWide) {
	    Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf)+1);
	}
	length = Tcl_DStringLength(&buf) + 1;

	result = (*regWinProcs->regSetValueExProc)(key, valueName, 0,
                (DWORD) type, (BYTE *) data, (DWORD) length);
	Tcl_DStringFree(&buf);
    } else {
	BYTE *data;


	/*
	 * Store binary data in the registry.
	 */

	data = (BYTE *) Tcl_GetByteArrayFromObj(dataObj, &length);
	result = (*regWinProcs->regSetValueExProc)(key, valueName, 0,
                (DWORD) type, data, (DWORD) length);
    }

    Tcl_DStringFree(&nameBuf);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp,
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

1428

1429

1430
1431
1432
1433


1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
 *----------------------------------------------------------------------
 */

static int
BroadcastValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    LRESULT result;
    DWORD_PTR sendResult;
    int timeout = 3000;
    size_t len;
    const char *str;
    Tcl_Obj *objPtr;
    WCHAR *wstr;

    Tcl_DString ds;



    if (objc == 3) {
	str = Tcl_GetString(objv[1]);
	len = objv[1]->length;
	if ((len < 2) || (*str != '-') || strncmp(str, "-timeout", len)) {


	    return TCL_BREAK;
	}
	if (Tcl_GetIntFromObj(interp, objv[2], &timeout) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    str = Tcl_GetString(objv[0]);
    Tcl_DStringInit(&ds);
    wstr = Tcl_UtfToWCharDString(str, objv[0]->length, &ds);
    if (Tcl_DStringLength(&ds) == 0) {
	wstr = NULL;
    }

    /*
     * Use the ignore the result.
     */

    result = SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE,
	    (WPARAM) 0, (LPARAM) wstr, SMTO_ABORTIFHUNG, (UINT) timeout, &sendResult);
    Tcl_DStringFree(&ds);

    objPtr = Tcl_NewObj();
    Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj((Tcl_WideInt) result));
    Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewWideIntObj((Tcl_WideInt) sendResult));
    Tcl_SetObjResult(interp, objPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|



|
|
|

|
>
|
>
|
>
|
|
<
|
>
>
|

|




|
<
<
|
|






|
|
<


|
|







1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418


1419
1420
1421
1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
 *----------------------------------------------------------------------
 */

static int
BroadcastValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument values. */
{
    LRESULT result;
    DWORD_PTR sendResult;
    UINT timeout = 3000;
    int len;
    CONST char *str;
    Tcl_Obj *objPtr;

    if ((objc != 3) && (objc != 5)) {
	Tcl_WrongNumArgs(interp, 2, objv, "keyName ?-timeout millisecs?");
	return TCL_ERROR;
    }

    if (objc > 3) {
	str = Tcl_GetStringFromObj(objv[3], &len);

	if ((len < 2) || (*str != '-')
		|| strncmp(str, "-timeout", (size_t) len)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "keyName ?-timeout millisecs?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[4], (int *) &timeout) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    str = Tcl_GetStringFromObj(objv[2], &len);


    if (len == 0) {
	str = NULL;
    }

    /*
     * Use the ignore the result.
     */

    result = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
	    (WPARAM) 0, (LPARAM) str, SMTO_ABORTIFHUNG, timeout, &sendResult);


    objPtr = Tcl_NewObj();
    Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) result));
    Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) sendResult));
    Tcl_SetObjResult(interp, objPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

















1501
1502

1503
1504

1505
1506
1507

1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531

static void
AppendSystemError(
    Tcl_Interp *interp,		/* Current interpreter. */
    DWORD error)		/* Result code from error. */
{
    int length;
    WCHAR *tMsgPtr, **tMsgPtrPtr = &tMsgPtr;
    const char *msg;
    char id[TCL_INTEGER_SPACE], msgBuf[24 + TCL_INTEGER_SPACE];
    Tcl_DString ds;
    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);

    if (Tcl_IsShared(resultPtr)) {
	resultPtr = Tcl_DuplicateObj(resultPtr);
    }
    length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
	    | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) tMsgPtrPtr,
	    0, NULL);
    if (length == 0) {

















	sprintf(msgBuf, "unknown error: %ld", error);
	msg = msgBuf;

    } else {
	char *msgPtr;


	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString(tMsgPtr, wcslen(tMsgPtr), &ds);

	LocalFree(tMsgPtr);

	msgPtr = Tcl_DStringValue(&ds);
	length = Tcl_DStringLength(&ds);

	/*
	 * Trim the trailing CR/LF from the system message.
	 */

	if (msgPtr[length-1] == '\n') {
	    --length;
	}
	if (msgPtr[length-1] == '\r') {
	    --length;
	}
	msgPtr[length] = 0;
	msg = msgPtr;
    }

    sprintf(id, "%ld", error);
    Tcl_SetErrorCode(interp, "WINDOWS", id, msg, NULL);
    Tcl_AppendToObj(resultPtr, msg, length);
    Tcl_SetObjResult(interp, resultPtr);








|
|









|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>

<
>

|
|
>
|

|






|
|

|
|

<
<







1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515


1516
1517
1518
1519
1520
1521
1522

static void
AppendSystemError(
    Tcl_Interp *interp,		/* Current interpreter. */
    DWORD error)		/* Result code from error. */
{
    int length;
    WCHAR *wMsgPtr, **wMsgPtrPtr = &wMsgPtr;
    char *msg;
    char id[TCL_INTEGER_SPACE], msgBuf[24 + TCL_INTEGER_SPACE];
    Tcl_DString ds;
    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);

    if (Tcl_IsShared(resultPtr)) {
	resultPtr = Tcl_DuplicateObj(resultPtr);
    }
    length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
	    | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) wMsgPtrPtr,
	    0, NULL);
    if (length == 0) {
	char *msgPtr;

	length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
		| FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &msgPtr,
		0, NULL);
	if (length > 0) {
	    wMsgPtr = (WCHAR *) LocalAlloc(LPTR, (length + 1) * sizeof(WCHAR));
	    MultiByteToWideChar(CP_ACP, 0, msgPtr, length + 1, wMsgPtr,
		    length + 1);
	    LocalFree(msgPtr);
	}
    }
    if (length == 0) {
	if (error == ERROR_CALL_NOT_IMPLEMENTED) {
	    msg = "function not supported under Win32s";
	} else {
	    sprintf(msgBuf, "unknown error: %ld", error);
	    msg = msgBuf;
	}
    } else {

	Tcl_Encoding encoding;

	encoding = Tcl_GetEncoding(NULL, "unicode");
	Tcl_ExternalToUtfDString(encoding, (char *) wMsgPtr, -1, &ds);
	Tcl_FreeEncoding(encoding);
	LocalFree(wMsgPtr);

	msg = Tcl_DStringValue(&ds);
	length = Tcl_DStringLength(&ds);

	/*
	 * Trim the trailing CR/LF from the system message.
	 */

	if (msg[length-1] == '\n') {
	    msg[--length] = 0;
	}
	if (msg[length-1] == '\r') {
	    msg[--length] = 0;
	}


    }

    sprintf(id, "%ld", error);
    Tcl_SetErrorCode(interp, "WINDOWS", id, msg, NULL);
    Tcl_AppendToObj(resultPtr, msg, length);
    Tcl_SetObjResult(interp, resultPtr);

1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
 */

static DWORD
ConvertDWORD(
    DWORD type,			/* Either REG_DWORD or REG_DWORD_BIG_ENDIAN */
    DWORD value)		/* The value to be converted. */
{
    const DWORD order = 1;
    DWORD localType;

    /*
     * Check to see if the low bit is in the first byte.
     */

    localType = (*((const char *) &order) == 1)
	    ? REG_DWORD : REG_DWORD_BIG_ENDIAN;
    return (type != localType) ? (DWORD) SWAPLONG(value) : value;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|






<
|










1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556

1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
 */

static DWORD
ConvertDWORD(
    DWORD type,			/* Either REG_DWORD or REG_DWORD_BIG_ENDIAN */
    DWORD value)		/* The value to be converted. */
{
    DWORD order = 1;
    DWORD localType;

    /*
     * Check to see if the low bit is in the first byte.
     */


    localType = (*((char*) &order) == 1) ? REG_DWORD : REG_DWORD_BIG_ENDIAN;
    return (type != localType) ? (DWORD) SWAPLONG(value) : value;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinSerial.c.

1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
 *----------------------------------------------------------------------
 *
 * TclWinSerialOpen --
 *
 *	Opens or Reopens the serial port with the OVERLAPPED FLAG set
 *
 * Results:
 *	Returns the new handle, or INVALID_HANDLE_VALUE.
 *	If an existing channel is specified it is closed and reopened.
 *
 * Side effects:
 *	May close/reopen the original handle
 *
 *----------------------------------------------------------------------
 */







|







1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
 *----------------------------------------------------------------------
 *
 * TclWinSerialOpen --
 *
 *	Opens or Reopens the serial port with the OVERLAPPED FLAG set
 *
 * Results:
 *	Returns the new handle, or INVALID_HANDLE_VALUE. 
 *	If an existing channel is specified it is closed and reopened.
 *
 * Side effects:
 *	May close/reopen the original handle
 *
 *----------------------------------------------------------------------
 */
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
    infoPtr->sysBufWrite = 4096;

    /*
     * Use the pointer to keep the channel names unique, in case the handles
     * are shared between multiple channels (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName,
	    (ClientData) infoPtr, permissions);


    SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite);
    PurgeComm(handle,







|







1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
    infoPtr->sysBufWrite = 4096;

    /*
     * Use the pointer to keep the channel names unique, in case the handles
     * are shared between multiple channels (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t)infoPtr);

    infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName,
	    (ClientData) infoPtr, permissions);


    SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite);
    PurgeComm(handle,

Changes to win/tclWinSock.c.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 *          all the OS messages are translated to through the EventSource (2)
 *          driven by the OS messages.
 *
 *   (Ad 2) The main functions for this are SocketSetupProc() and
 *          SocketCheckProc().
 */

#include <winsock2.h>
#include <ws2tcpip.h>
#include "tclWinInt.h"

#ifdef _MSC_VER
#   pragma comment (lib, "ws2_32")
#endif

/*







<
<







41
42
43
44
45
46
47


48
49
50
51
52
53
54
 *          all the OS messages are translated to through the EventSource (2)
 *          driven by the OS messages.
 *
 *   (Ad 2) The main functions for this are SocketSetupProc() and
 *          SocketCheckProc().
 */



#include "tclWinInt.h"

#ifdef _MSC_VER
#   pragma comment (lib, "ws2_32")
#endif

/*
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Static functions defined in this file.
 */

static SocketInfo *	CreateSocket(Tcl_Interp *interp, int port,
			    const char *host, int server, const char *myaddr,
			    int myport, int async);
static int		CreateSocketAddress(struct sockaddr_in *sockaddrPtr,
			    const char *host, int port, int willBind);
static void		InitSockets(void);
static SocketInfo *	NewSocketInfo(SOCKET socket);
static void		SocketExitHandler(ClientData clientData);
static LRESULT CALLBACK	SocketProc(HWND hwnd, UINT message, WPARAM wParam,
			    LPARAM lParam);
static int		SocketsEnabled(void);
static void		TcpAccept(SocketInfo *infoPtr);







|
|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 * Static functions defined in this file.
 */

static SocketInfo *	CreateSocket(Tcl_Interp *interp, int port,
			    const char *host, int server, const char *myaddr,
			    int myport, int async);
static int		CreateSocketAddress(LPSOCKADDR_IN sockaddrPtr,
			    const char *host, int port);
static void		InitSockets(void);
static SocketInfo *	NewSocketInfo(SOCKET socket);
static void		SocketExitHandler(ClientData clientData);
static LRESULT CALLBACK	SocketProc(HWND hwnd, UINT message, WPARAM wParam,
			    LPARAM lParam);
static int		SocketsEnabled(void);
static void		TcpAccept(SocketInfo *infoPtr);
356
357
358
359
360
361
362

363
364
365
366
367
368
369
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
SocketsEnabled(void)
{
    int enabled;
    Tcl_MutexLock(&socketMutex);
    enabled = (initialized == 1);
    Tcl_MutexUnlock(&socketMutex);







>







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static int
SocketsEnabled(void)
{
    int enabled;
    Tcl_MutexLock(&socketMutex);
    enabled = (initialized == 1);
    Tcl_MutexUnlock(&socketMutex);
384
385
386
387
388
389
390

391
392
393
394
395
396
397
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static void
SocketExitHandler(
    ClientData clientData)		/* Not used. */
{
    Tcl_MutexLock(&socketMutex);
    /*
     * Make sure the socket event handling window is cleaned-up for, at







>







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static void
SocketExitHandler(
    ClientData clientData)		/* Not used. */
{
    Tcl_MutexLock(&socketMutex);
    /*
     * Make sure the socket event handling window is cleaned-up for, at
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
	/*
	 * Throw the readable event if an async connect failed.
	 */

	if (infoPtr->lastError) {

	    mask |= TCL_READABLE;

	} else {
	    fd_set readFds;
	    struct timeval timeout;

	    /*
	     * We must check to see if data is really available, since someone
	     * could have consumed the data in the meantime. Turn off async







|







687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
	/*
	 * Throw the readable event if an async connect failed.
	 */

	if (infoPtr->lastError) {

	    mask |= TCL_READABLE;
	    
	} else {
	    fd_set readFds;
	    struct timeval timeout;

	    /*
	     * We must check to see if data is really available, since someone
	     * could have consumed the data in the meantime. Turn off async
782
783
784
785
786
787
788

789
790
791
792
793
794
795
 *
 * Side effects:
 *	Closes the socket.
 *
 *----------------------------------------------------------------------
 */


static int
TcpCloseProc(
    ClientData instanceData,	/* The socket to close. */
    Tcl_Interp *interp)		/* Unused. */
{
    SocketInfo *infoPtr = (SocketInfo *) instanceData;
    /* TIP #218 */







>







782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
 *
 * Side effects:
 *	Closes the socket.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
static int
TcpCloseProc(
    ClientData instanceData,	/* The socket to close. */
    Tcl_Interp *interp)		/* Unused. */
{
    SocketInfo *infoPtr = (SocketInfo *) instanceData;
    /* TIP #218 */
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
				 * 0 for a client socket. */
    const char *myaddr,		/* Optional client-side address */
    int myport,			/* Optional client-side port */
    int async)			/* If nonzero, connect client socket
				 * asynchronously. */
{
    u_long flag = 1;		/* Indicates nonblocking mode. */
    struct sockaddr_in sockaddr;   /* Socket address */
    struct sockaddr_in mysockaddr; /* Socket address for client */
    SOCKET sock = INVALID_SOCKET;
    SocketInfo *infoPtr=NULL;	/* The returned value. */
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
	return NULL;
    }

    if (!CreateSocketAddress(&sockaddr, host, port, server)) {
	goto error;
    }
    if ((myaddr != NULL || myport != 0) &&
	    !CreateSocketAddress(&mysockaddr, myaddr, myport, 1)) {
	goto error;
    }

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
	goto error;
    }







|
|















|



|







916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
				 * 0 for a client socket. */
    const char *myaddr,		/* Optional client-side address */
    int myport,			/* Optional client-side port */
    int async)			/* If nonzero, connect client socket
				 * asynchronously. */
{
    u_long flag = 1;		/* Indicates nonblocking mode. */
    SOCKADDR_IN sockaddr;	/* Socket address */
    SOCKADDR_IN mysockaddr;	/* Socket address for client */
    SOCKET sock = INVALID_SOCKET;
    SocketInfo *infoPtr=NULL;	/* The returned value. */
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
	return NULL;
    }

    if (!CreateSocketAddress(&sockaddr, host, port)) {
	goto error;
    }
    if ((myaddr != NULL || myport != 0) &&
	    !CreateSocketAddress(&mysockaddr, myaddr, myport)) {
	goto error;
    }

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
	goto error;
    }
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
	infoPtr->selectEvents = FD_ACCEPT;
	infoPtr->watchEvents |= FD_ACCEPT;

	/*
	 * Register for interest in events in the select mask. Note that this
	 * automatically places the socket into non-blocking mode.
	 */

	ioctlsocket(sock, (long) FIONBIO, &flag);
	SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
		(LPARAM) infoPtr);

    } else {
	/*
	 * Try to bind to a local port, if specified.







|







1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
	infoPtr->selectEvents = FD_ACCEPT;
	infoPtr->watchEvents |= FD_ACCEPT;

	/*
	 * Register for interest in events in the select mask. Note that this
	 * automatically places the socket into non-blocking mode.
	 */
    
	ioctlsocket(sock, (long) FIONBIO, &flag);
	SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
		(LPARAM) infoPtr);

    } else {
	/*
	 * Try to bind to a local port, if specified.
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
	     * Set connect mask to connect events
	     * This is activated by a SOCKET_SELECT message to the notifier
	     * thread.
	     */

	    infoPtr->selectEvents |= FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE;
	    infoPtr->flags |= SOCKET_ASYNC_CONNECT;

	    /*
	     * Free list lock
	     */
	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Activate accept notification and put in async mode







|







1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
	     * Set connect mask to connect events
	     * This is activated by a SOCKET_SELECT message to the notifier
	     * thread.
	     */

	    infoPtr->selectEvents |= FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE;
	    infoPtr->flags |= SOCKET_ASYNC_CONNECT;
	    
	    /*
	     * Free list lock
	     */
	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Activate accept notification and put in async mode
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158

1159

1160
1161


1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214












1215
1216
1217
1218
1219
1220
1221
 *----------------------------------------------------------------------
 */

static int
CreateSocketAddress(
    LPSOCKADDR_IN sockaddrPtr,	/* Socket address */
    const char *host,		/* Host. NULL implies INADDR_ANY */
    int port,			/* Port number */
    int willBind)		/* Is this an address to bind() to or
				 * to connect() to? */
{
    struct addrinfo hints, *resPtr = NULL;

    char *native;

    Tcl_DString ds;
    int result;



    if (host == NULL) {
	sockaddrPtr->sin_family = AF_INET;
	sockaddrPtr->sin_addr.s_addr = INADDR_ANY;
    addPort:
	sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
	return 1;
    }

    (void) memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    if (willBind) {
	hints.ai_flags |= AI_PASSIVE;

    }

    /*
     * Note that getaddrinfo() *is* thread-safe. If a platform doesn't get
     * that right, it shouldn't use this part of the code.
     */

    native = Tcl_UtfToExternalDString(NULL, host, -1, &ds);
    result = getaddrinfo(native, NULL, &hints, &resPtr);
    Tcl_DStringFree(&ds);
    if (result == 0) {
	memcpy(sockaddrPtr, resPtr->ai_addr, sizeof(struct sockaddr_in));
	freeaddrinfo(resPtr);
	goto addPort;
    }

    /*
     * errno corresponding result ...
     */

    switch (result) {
    case EAI_NONAME:
    case EAI_SERVICE:
#if defined(EAI_ADDRFAMILY) && EAI_ADDRFAMILY != EAI_NONAME
    case EAI_ADDRFAMILY:
#endif
#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
    case EAI_NODATA:
#endif
#ifdef	EHOSTUNREACH
	Tcl_SetErrno(EHOSTUNREACH);
	return 0;
#endif
    default:
#ifdef ENXIO
	Tcl_SetErrno(ENXIO);
#endif

	return 0;
    }












}

/*
 *----------------------------------------------------------------------
 *
 * WaitForSocketEvent --
 *







|
<
<

|
>
|
>
|
|
>
>

|
<
<
|
<
|


|
|
<
>
|
<
>
|
|
<
<
<
<
|
<
|
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<
<
<
<
<
<

|
<
|
<

|

>
|
|
>
>
>
>
>
>
>
>
>
>
>
>







1148
1149
1150
1151
1152
1153
1154
1155


1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166


1167

1168
1169
1170
1171
1172

1173
1174

1175
1176
1177




1178

1179






1180



1181

1182







1183
1184

1185

1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
 *----------------------------------------------------------------------
 */

static int
CreateSocketAddress(
    LPSOCKADDR_IN sockaddrPtr,	/* Socket address */
    const char *host,		/* Host. NULL implies INADDR_ANY */
    int port)			/* Port number */


{
    struct hostent *hostent;	/* Host database entry */
    struct in_addr addr;	/* For 64/32 bit madness */

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {


	Tcl_SetErrno(EFAULT);

	return 0;
    }

    ZeroMemory(sockaddrPtr, sizeof(SOCKADDR_IN));
    sockaddrPtr->sin_family = AF_INET;

    sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
    if (host == NULL) {

	addr.s_addr = INADDR_ANY;
    } else {
	addr.s_addr = inet_addr(host);




	if (addr.s_addr == INADDR_NONE) {

	    hostent = gethostbyname(host);






	    if (hostent != NULL) {



		memcpy(&addr, hostent->h_addr, (size_t) hostent->h_length);

	    } else {







#ifdef	EHOSTUNREACH
		Tcl_SetErrno(EHOSTUNREACH);

#else

#ifdef ENXIO
		Tcl_SetErrno(ENXIO);
#endif
#endif
		return 0;	/* Error. */
	    }
	}
    }

    /*
     * NOTE: On 64 bit machines the assignment below is rumored to not do the
     * right thing. Please report errors related to this if you observe
     * incorrect behavior on 64 bit machines such as DEC Alphas. Should we
     * modify this code to do an explicit memcpy?
     */

    sockaddrPtr->sin_addr.s_addr = addr.s_addr;
    return 1;			/* Success. */
}

/*
 *----------------------------------------------------------------------
 *
 * WaitForSocketEvent --
 *
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
     * Don't do that if we are waiting for a connect as we may miss
     * a connect (bug 336441ed59).
     */

    if ( 0 == (events & FD_CONNECT) ) {
        SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT,
                (LPARAM) infoPtr);

        SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
                (LPARAM) infoPtr);
    }

    while (1) {
	if (infoPtr->lastError) {
	    *errorCodePtr = infoPtr->lastError;







|







1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
     * Don't do that if we are waiting for a connect as we may miss
     * a connect (bug 336441ed59).
     */

    if ( 0 == (events & FD_CONNECT) ) {
        SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT,
                (LPARAM) infoPtr);
    
        SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
                (LPARAM) infoPtr);
    }

    while (1) {
	if (infoPtr->lastError) {
	    *errorCodePtr = infoPtr->lastError;
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
     */

    infoPtr = CreateSocket(interp, port, host, 0, myaddr, myport, async);
    if (infoPtr == NULL) {
	return NULL;
    }

    sprintf(channelName, "sock%" TCL_Z_MODIFIER "u", (size_t)infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
	return (Tcl_Channel) NULL;







|







1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
     */

    infoPtr = CreateSocket(interp, port, host, 0, myaddr, myport, async);
    if (infoPtr == NULL) {
	return NULL;
    }

    sprintf(channelName, "sock%" TCL_I_MODIFIER "u", (size_t)infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
	return (Tcl_Channel) NULL;
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
     * Start watching for read/write events on the socket.
     */

    infoPtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
	    (WPARAM) SELECT, (LPARAM) infoPtr);

    sprintf(channelName, "sock%" TCL_Z_MODIFIER "u", (size_t)infoPtr->socket);
    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto crlf");
    return infoPtr->channel;
}

/*







|







1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
     * Start watching for read/write events on the socket.
     */

    infoPtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
	    (WPARAM) SELECT, (LPARAM) infoPtr);

    sprintf(channelName, "sock%" TCL_I_MODIFIER "u", (size_t)infoPtr->socket);
    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto crlf");
    return infoPtr->channel;
}

/*
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
    if (infoPtr == NULL) {
	return NULL;
    }

    infoPtr->acceptProc = acceptProc;
    infoPtr->acceptProcData = acceptProcData;

    sprintf(channelName, "sock%" TCL_Z_MODIFIER "u", (size_t)infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, 0);
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-eofchar", "")
	    == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
	return (Tcl_Channel) NULL;







|







1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
    if (infoPtr == NULL) {
	return NULL;
    }

    infoPtr->acceptProc = acceptProc;
    infoPtr->acceptProcData = acceptProcData;

    sprintf(channelName, "sock%" TCL_I_MODIFIER "u", (size_t)infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, 0);
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-eofchar", "")
	    == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
	return (Tcl_Channel) NULL;
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
     * Select on read/write events and create the channel.
     */

    newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE);
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
	    (WPARAM) SELECT, (LPARAM) newInfoPtr);

    sprintf(channelName, "sock%" TCL_Z_MODIFIER "u", (size_t)newInfoPtr->socket);
    newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) newInfoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, newInfoPtr->channel);
	return;
    }







|







1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
     * Select on read/write events and create the channel.
     */

    newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE);
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
	    (WPARAM) SELECT, (LPARAM) newInfoPtr);

    sprintf(channelName, "sock%" TCL_I_MODIFIER "u", (size_t)newInfoPtr->socket);
    newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) newInfoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_Close((Tcl_Interp *) NULL, newInfoPtr->channel);
	return;
    }
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
	Tcl_MutexUnlock(&socketMutex);

	tsdPtr = TCL_TSD_INIT(&dataKey);

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
	infoPtr->nextPtr = tsdPtr->socketList;
	tsdPtr->socketList = infoPtr;

	if (infoPtr == tsdPtr->pendingSocketInfo) {
	    tsdPtr->pendingSocketInfo = NULL;
	}

	SetEvent(tsdPtr->socketListLock);

	notifyCmd = SELECT;
    } else {
	SocketInfo **nextPtrPtr;
	int removed = 0;








|



|







2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
	Tcl_MutexUnlock(&socketMutex);

	tsdPtr = TCL_TSD_INIT(&dataKey);

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
	infoPtr->nextPtr = tsdPtr->socketList;
	tsdPtr->socketList = infoPtr;
	
	if (infoPtr == tsdPtr->pendingSocketInfo) {
	    tsdPtr->pendingSocketInfo = NULL;
	}
	
	SetEvent(tsdPtr->socketListLock);

	notifyCmd = SELECT;
    } else {
	SocketInfo **nextPtrPtr;
	int removed = 0;

Changes to win/tclWinTest.c.

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
    typedef BOOL (WINAPI *lookupAccountNameADef)(LPCSTR, LPCSTR, PSID,
	    PDWORD, LPSTR, LPDWORD, PSID_NAME_USE);
    typedef BOOL (WINAPI *getFileSecurityADef)(LPCSTR, SECURITY_INFORMATION,
	    PSECURITY_DESCRIPTOR, DWORD, LPDWORD);

    static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION
	    | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
    /* don't deny DELETE mask (reset writable only, allow test-cases cleanup) */
    static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE
	    | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA
	    | FILE_WRITE_DATA
	    /* | DELETE */;

    /*
     * References to security functions (only available on NT and later).
     */

    static getSidLengthRequiredDef getSidLengthRequiredProc;
    static initializeSidDef initializeSidProc;







<


|
<







416
417
418
419
420
421
422

423
424
425

426
427
428
429
430
431
432
    typedef BOOL (WINAPI *lookupAccountNameADef)(LPCSTR, LPCSTR, PSID,
	    PDWORD, LPSTR, LPDWORD, PSID_NAME_USE);
    typedef BOOL (WINAPI *getFileSecurityADef)(LPCSTR, SECURITY_INFORMATION,
	    PSECURITY_DESCRIPTOR, DWORD, LPDWORD);

    static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION
	    | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;

    static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE
	    | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA
	    | FILE_WRITE_DATA | DELETE;


    /*
     * References to security functions (only available on NT and later).
     */

    static getSidLengthRequiredDef getSidLengthRequiredProc;
    static initializeSidDef initializeSidProc;
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
     * One time initialization, dynamically load Windows NT features
     */

    if (!initialized) {
	TCL_DECLARE_MUTEX(initializeMutex)
	Tcl_MutexLock(&initializeMutex);
	if (!initialized) {
	    HMODULE handle = GetModuleHandle(TEXT("ADVAPI32"));
	    if (handle == NULL) {
	    	handle = GetModuleHandle(TEXT("ADVAPI"));
	    }

	    if (handle != NULL) {
		setNamedSecurityInfoProc = (setNamedSecurityInfoADef)
			GetProcAddress(handle, "SetNamedSecurityInfoA");
		getFileSecurityProc = (getFileSecurityADef)
			GetProcAddress(handle, "GetFileSecurityA");
		getAceProc = (getAceDef)







|
<
<
<







462
463
464
465
466
467
468
469



470
471
472
473
474
475
476
     * One time initialization, dynamically load Windows NT features
     */

    if (!initialized) {
	TCL_DECLARE_MUTEX(initializeMutex)
	Tcl_MutexLock(&initializeMutex);
	if (!initialized) {
	    HMODULE handle = GetModuleHandle(TEXT("ADVAPI"));




	    if (handle != NULL) {
		setNamedSecurityInfoProc = (setNamedSecurityInfoADef)
			GetProcAddress(handle, "SetNamedSecurityInfoA");
		getFileSecurityProc = (getFileSecurityADef)
			GetProcAddress(handle, "GetFileSecurityA");
		getAceProc = (getAceDef)
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
	if (!addAceProc(newAcl, ACL_REVISION, MAXDWORD, (PACL *)pACE2,
		((PACE_HEADER) pACE2)->AceSize)) {
	    goto done;
	}
    }

    /*
     * Apply the new ACL. Note PROTECTED_DACL_SECURITY_INFORMATION can be used
     * to remove inherited ACL (we need to overwrite the default ACL's in this case)
     */

    if (set_readOnly == acl_readOnly_found || setNamedSecurityInfoProc(
	    (LPSTR) nativePath, SE_FILE_OBJECT,
	    DACL_SECURITY_INFORMATION /*| PROTECTED_DACL_SECURITY_INFORMATION*/,
	    NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
	res = 0;
    }

  done:
    if (secDesc) {
	ckfree((char *) secDesc);







|
<



|
<







657
658
659
660
661
662
663
664

665
666
667
668

669
670
671
672
673
674
675
	if (!addAceProc(newAcl, ACL_REVISION, MAXDWORD, (PACL *)pACE2,
		((PACE_HEADER) pACE2)->AceSize)) {
	    goto done;
	}
    }

    /*
     * Apply the new ACL.

     */

    if (set_readOnly == acl_readOnly_found || setNamedSecurityInfoProc(
	    (LPSTR) nativePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,

	    NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
	res = 0;
    }

  done:
    if (secDesc) {
	ckfree((char *) secDesc);

Added win/tclWinThrd.h.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * tclWinThrd.h --
 *
 *      This header file defines things for thread support.
 *
 * Copyright (c) 1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
 
#ifndef _TCLWINTHRD
#define _TCLWINTHRD

#ifdef TCL_THREADS

#endif /* TCL_THREADS */

#endif /* _TCLWINTHRD */

Changes to win/tclWinTime.c.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

typedef struct TimeInfo {
    CRITICAL_SECTION cs;	/* Mutex guarding this structure. */
    int initialized;		/* Flag == 1 if this structure is
				 * initialized. */
    int perfCounterAvailable;	/* Flag == 1 if the hardware has a performance
				 * counter. */
    DWORD calibrationInterv;	/* Calibration interval in seconds (start 1 sec) */
    HANDLE calibrationThread;	/* Handle to the thread that keeps the virtual
				 * clock calibrated. */
    HANDLE readyEvent;		/* System event used to trigger the requesting
				 * thread when the clock calibration procedure
				 * is initialized for the first time. */
    HANDLE exitEvent; 		/* Event to signal out of an exit handler to
				 * tell the calibration loop to terminate. */
    LARGE_INTEGER nominalFreq;	/* Nominal frequency of the system performance
				 * counter, that is, the value returned from
				 * QueryPerformanceFrequency. */

    /*
     * The following values are used for calculating virtual time. Virtual
     * time is always equal to:
     *    lastFileTime + (current perf counter - lastCounter)
     *				* 10000000 / curCounterFreq
     * and lastFileTime and lastCounter are updated any time that virtual time
     * is returned to a caller.
     */

    ULARGE_INTEGER fileTimeLastCall;
    LARGE_INTEGER perfCounterLastCall;
    LARGE_INTEGER curCounterFreq;
    LARGE_INTEGER posixEpoch;	/* Posix epoch expressed as 100-ns ticks since
				 * the windows epoch. */

    /*
     * Data used in developing the estimate of performance counter frequency
     */

    Tcl_WideUInt fileTimeSample[SAMPLES];
				/* Last 64 samples of system time. */
    Tcl_WideInt perfCounterSample[SAMPLES];
				/* Last 64 samples of performance counter. */
    int sampleNo;		/* Current sample number. */
} TimeInfo;

static TimeInfo timeInfo = {
    { NULL, 0, 0, NULL, NULL, 0 },
    0,
    0,
    1,
    (HANDLE) NULL,
    (HANDLE) NULL,
    (HANDLE) NULL,
#ifdef HAVE_CAST_TO_UNION
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (ULARGE_INTEGER) (DWORDLONG) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
#else
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
#endif
    { 0 },
    { 0 },
    0
};

/*
 * Scale to convert wide click values from the TclpGetWideClicks native
 * resolution to microsecond resolution and back.
 */
static struct {
    int initialized;		/* 1 if initialized, 0 otherwise */
    int perfCounter;		/* 1 if performance counter usable for wide
				 * clicks */
    double microsecsScale;	/* Denominator scale between clock / microsecs */
} wideClick = {0, 0, 0.0};


/*
 * Declarations for functions defined later in this file.
 */

static struct tm *	ComputeGMT(const time_t *tp);
static void		StopCalibration(ClientData clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
static void 		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(Tcl_WideUInt fileTime,
			    Tcl_WideInt perfCounter, Tcl_WideInt perfFreq);
static Tcl_WideInt	AccumulateSample(Tcl_WideInt perfCounter,
			    Tcl_WideUInt fileTime);
static void		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);
static Tcl_WideInt	NativeGetMicroseconds(void);
static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */








<










>












<
<













|


<








<

|
|
|
|
<





<
<
<
<
<
<
<
<
<
<
<
<















<







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
120
121
122
123
124
125

126
127
128
129
130
131
132

typedef struct TimeInfo {
    CRITICAL_SECTION cs;	/* Mutex guarding this structure. */
    int initialized;		/* Flag == 1 if this structure is
				 * initialized. */
    int perfCounterAvailable;	/* Flag == 1 if the hardware has a performance
				 * counter. */

    HANDLE calibrationThread;	/* Handle to the thread that keeps the virtual
				 * clock calibrated. */
    HANDLE readyEvent;		/* System event used to trigger the requesting
				 * thread when the clock calibration procedure
				 * is initialized for the first time. */
    HANDLE exitEvent; 		/* Event to signal out of an exit handler to
				 * tell the calibration loop to terminate. */
    LARGE_INTEGER nominalFreq;	/* Nominal frequency of the system performance
				 * counter, that is, the value returned from
				 * QueryPerformanceFrequency. */

    /*
     * The following values are used for calculating virtual time. Virtual
     * time is always equal to:
     *    lastFileTime + (current perf counter - lastCounter)
     *				* 10000000 / curCounterFreq
     * and lastFileTime and lastCounter are updated any time that virtual time
     * is returned to a caller.
     */

    ULARGE_INTEGER fileTimeLastCall;
    LARGE_INTEGER perfCounterLastCall;
    LARGE_INTEGER curCounterFreq;



    /*
     * Data used in developing the estimate of performance counter frequency
     */

    Tcl_WideUInt fileTimeSample[SAMPLES];
				/* Last 64 samples of system time. */
    Tcl_WideInt perfCounterSample[SAMPLES];
				/* Last 64 samples of performance counter. */
    int sampleNo;		/* Current sample number. */
} TimeInfo;

static TimeInfo timeInfo = {
    { NULL },
    0,
    0,

    (HANDLE) NULL,
    (HANDLE) NULL,
    (HANDLE) NULL,
#ifdef HAVE_CAST_TO_UNION
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (ULARGE_INTEGER) (DWORDLONG) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,

#else
    0,
    0,
    0,
    0,

#endif
    { 0 },
    { 0 },
    0
};













/*
 * Declarations for functions defined later in this file.
 */

static struct tm *	ComputeGMT(const time_t *tp);
static void		StopCalibration(ClientData clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
static void 		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(Tcl_WideUInt fileTime,
			    Tcl_WideInt perfCounter, Tcl_WideInt perfFreq);
static Tcl_WideInt	AccumulateSample(Tcl_WideInt perfCounter,
			    Tcl_WideUInt fileTime);
static void		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);

static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
 *
 *----------------------------------------------------------------------
 */

unsigned long
TclpGetSeconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;

    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	return usecSincePosixEpoch / 1000000;
    } else {
	Tcl_Time t;

	tclGetTimeProcPtr(&t, tclTimeClientData);	/* Tcl_GetTime inlined. */
	return t.sec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --
 *
 *	This procedure returns a value that represents the highest resolution
 *	clock available on the system. There are no guarantees on what the
 *	resolution will be. In Tcl we will call this value a "click". The
 *	start time is also system dependent.
 *
 * Results:
 *	Number of clicks from some start time.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long
TclpGetClicks(void)
{
    Tcl_WideInt usecSincePosixEpoch;

    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	return (unsigned long)usecSincePosixEpoch;
    } else {
	/*
	* Use the Tcl_GetTime abstraction to get the time in microseconds, as
	* nearly as we can, and return it.
	*/

	Tcl_Time now;		/* Current Tcl time */

	tclGetTimeProcPtr(&now, tclTimeClientData);	/* Tcl_GetTime inlined */
	return (unsigned long)(now.sec * 1000000) + now.usec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetWideClicks --
 *
 *	This procedure returns a WideInt value that represents the highest
 *	resolution clock in microseconds available on the system.
 *
 * Results:
 *	Number of microseconds (from some start time).
 *
 * Side effects:
 *	This should be used for time-delta resp. for measurement purposes
 *	only, because on some platforms can return microseconds from some
 *	start time (not from the epoch).
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetWideClicks(void)
{
    LARGE_INTEGER curCounter;

    if (!wideClick.initialized) {
	LARGE_INTEGER perfCounterFreq;

	/*
	 * The frequency of the performance counter is fixed at system boot and
	 * is consistent across all processors. Therefore, the frequency need
	 * only be queried upon application initialization.
	 */
	if (QueryPerformanceFrequency(&perfCounterFreq)) {
	    wideClick.perfCounter = 1;
	    wideClick.microsecsScale = 1000000.0 / perfCounterFreq.QuadPart;
	} else {
	    /* fallback using microseconds */
	    wideClick.perfCounter = 0;
	    wideClick.microsecsScale = 1;
	}

	wideClick.initialized = 1;
    }
    if (wideClick.perfCounter) {
	if (QueryPerformanceCounter(&curCounter)) {
	    return (Tcl_WideInt)curCounter.QuadPart;
	}
	/* fallback using microseconds */
	wideClick.perfCounter = 0;
	wideClick.microsecsScale = 1;
	return TclpGetMicroseconds();
    } else {
    	return TclpGetMicroseconds();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpWideClickInMicrosec --
 *
 *	This procedure return scale to convert wide click values from the
 *	TclpGetWideClicks native resolution to microsecond resolution
 *	and back.
 *
 * Results:
 * 	1 click in microseconds as double.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (!wideClick.initialized) {
    	(void)TclpGetWideClicks();	/* initialize */
    }
    return wideClick.microsecsScale;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetMicroseconds --
 *
 *	This procedure returns a WideInt value that represents the highest
 *	resolution clock in microseconds available on the system.
 *
 * Results:
 *	Number of microseconds (from the epoch).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetMicroseconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;

    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	return usecSincePosixEpoch;
    } else {
	/*
	* Use the Tcl_GetTime abstraction to get the time in microseconds, as
	* nearly as we can, and return it.
	*/

	Tcl_Time now;

	tclGetTimeProcPtr(&now, tclTimeClientData);	/* Tcl_GetTime inlined */
	return (((Tcl_WideInt)now.sec) * 1000000) + now.usec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetTimeZone --
 *







<
<
<
<
<
<
<
<
|

|
|
<










|













<
<
<
<
<
<
<
<
|
|
|
|

|
|
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<

<
<
<
<
<







150
151
152
153
154
155
156








157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184








185
186
187
188
189
190
191


192

193


194















195


























































































196





197





198
199
200
201
202
203
204
 *
 *----------------------------------------------------------------------
 */

unsigned long
TclpGetSeconds(void)
{








    Tcl_Time t;

    (*tclGetTimeProcPtr) (&t, tclTimeClientData);    /* Tcl_GetTime inlined. */
    return t.sec;

}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --
 *
 *	This procedure returns a value that represents the highest resolution
 *	clock available on the system. There are no guarantees on what the
 *	resolution will be. In Tcl we will call this value a "click". The
 *	start time is also system dependant.
 *
 * Results:
 *	Number of clicks from some start time.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long
TclpGetClicks(void)
{








    /*
     * Use the Tcl_GetTime abstraction to get the time in microseconds, as
     * nearly as we can, and return it.
     */

    Tcl_Time now;		/* Current Tcl time */
    unsigned long retval;	/* Value to return */




    (*tclGetTimeProcPtr) (&now, tclTimeClientData);   /* Tcl_GetTime inlined */


















    retval = (now.sec * 1000000) + now.usec;


























































































    return retval;











}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetTimeZone --
 *
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
 *----------------------------------------------------------------------
 */

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    Tcl_WideInt usecSincePosixEpoch;

    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
    } else {
    	tclGetTimeProcPtr(timePtr, tclTimeClientData);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NativeScaleTime --
 *







<
<
<
<
<
<
<
<
<
|
<







248
249
250
251
252
253
254









255

256
257
258
259
260
261
262
 *----------------------------------------------------------------------
 */

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{









    (*tclGetTimeProcPtr) (timePtr, tclTimeClientData);

}

/*
 *----------------------------------------------------------------------
 *
 * NativeScaleTime --
 *
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
     * Native scale is 1:1. Nothing is done.
     */
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetMicroseconds --
 *
 *	Gets the current system time in microseconds since the beginning
 *	of the epoch: 00:00 UCT, January 1, 1970.
 *
 * Results:
 *	Returns the wide integer with number of microseconds from the epoch, or
 *	0 if high resolution timer is not available.
 *
 * Side effects:
 *	On the first call, initializes a set of static variables to keep track
 *	of the base value of the performance counter, the corresponding wall
 *	clock (obtained through ftime) and the frequency of the performance
 *	counter. Also spins a thread whose function is to wake up periodically
 *	and monitor these values, adjusting them as necessary to correct for
 *	drift in the performance counter's oscillator.
 *
 *----------------------------------------------------------------------
 */

static inline Tcl_WideInt
NativeCalc100NsTicks(
    ULONGLONG fileTimeLastCall,
    LONGLONG perfCounterLastCall,
    LONGLONG curCounterFreq,
    LONGLONG curCounter
) {
    return fileTimeLastCall +
	((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
}

static Tcl_WideInt
NativeGetMicroseconds(void)
{
    /*
     * Initialize static storage on the first trip through.
     *
     * Note: Outer check for 'initialized' is a performance win since it
     * avoids an extra mutex lock in the common case.
     */

    if (!timeInfo.initialized) {
	TclpInitLock();
	if (!timeInfo.initialized) {
	    timeInfo.posixEpoch.LowPart = 0xD53E8000;
	    timeInfo.posixEpoch.HighPart = 0x019DB1DE;

	    timeInfo.perfCounterAvailable =
		    QueryPerformanceFrequency(&timeInfo.nominalFreq);

	    /*
	     * Some hardware abstraction layers use the CPU clock in place of
	     * the real-time clock as a performance counter reference. This
	     * results in:







|

|
|


|
<












|
|
|
<
<
|
<
<
<
<
|
|
<
|










<
<
<







281
282
283
284
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309


310




311
312

313
314
315
316
317
318
319
320
321
322
323



324
325
326
327
328
329
330
     * Native scale is 1:1. Nothing is done.
     */
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetTime --
 *
 *	TIP #233: Gets the current system time in seconds and microseconds
 *	since the beginning of the epoch: 00:00 UCT, January 1, 1970.
 *
 * Results:
 *	Returns the current time in timePtr.

 *
 * Side effects:
 *	On the first call, initializes a set of static variables to keep track
 *	of the base value of the performance counter, the corresponding wall
 *	clock (obtained through ftime) and the frequency of the performance
 *	counter. Also spins a thread whose function is to wake up periodically
 *	and monitor these values, adjusting them as necessary to correct for
 *	drift in the performance counter's oscillator.
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,


    ClientData clientData)




{
    struct _timeb t;


    /*
     * Initialize static storage on the first trip through.
     *
     * Note: Outer check for 'initialized' is a performance win since it
     * avoids an extra mutex lock in the common case.
     */

    if (!timeInfo.initialized) {
	TclpInitLock();
	if (!timeInfo.initialized) {



	    timeInfo.perfCounterAvailable =
		    QueryPerformanceFrequency(&timeInfo.nominalFreq);

	    /*
	     * Some hardware abstraction layers use the CPU clock in place of
	     * the real-time clock as a performance counter reference. This
	     * results in:
597
598
599
600
601
602
603
604
605
606
607
608
609










610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652
653
654
655
656
657


658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730

    if (timeInfo.perfCounterAvailable && timeInfo.curCounterFreq.QuadPart!=0) {
	/*
	 * Query the performance counter and use it to calculate the current
	 * time.
	 */

	ULONGLONG fileTimeLastCall;
	LONGLONG perfCounterLastCall, curCounterFreq;
				/* Copy with current data of calibration cycle */

	LARGE_INTEGER curCounter;
				/* Current performance counter. */











	QueryPerformanceCounter(&curCounter);

	/*
	 * Hold time section locked as short as possible
	 */
	EnterCriticalSection(&timeInfo.cs);

	fileTimeLastCall = timeInfo.fileTimeLastCall.QuadPart;
	perfCounterLastCall = timeInfo.perfCounterLastCall.QuadPart;
	curCounterFreq = timeInfo.curCounterFreq.QuadPart;

	LeaveCriticalSection(&timeInfo.cs);

	/*
	 * If calibration cycle occurred after we get curCounter
	 */

	if (curCounter.QuadPart <= perfCounterLastCall) {

	    /*
	     * Calibrated file-time is saved from posix in 100-ns ticks
	     */

	    return fileTimeLastCall / 10;
	}

	/*
	 * If it appears to be more than 1.1 seconds since the last trip
	 * through the calibration loop, the performance counter may have
	 * jumped forward. (See MSDN Knowledge Base article Q274323 for a
	 * description of the hardware problem that makes this test
	 * necessary.) If the counter jumps, we don't want to use it directly.
	 * Instead, we must return system time. Eventually, the calibration
	 * loop should recover.
	 */

	if (curCounter.QuadPart - perfCounterLastCall <
		11 * curCounterFreq * timeInfo.calibrationInterv / 10
	) {
	    /* Calibrated file-time is saved from posix in 100-ns ticks */
	    return NativeCalc100NsTicks(fileTimeLastCall,
		perfCounterLastCall, curCounterFreq, curCounter.QuadPart) / 10;

	}
    }

    /*
     * High resolution timer is not available.
     */


    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetTime --
 *
 *	TIP #233: Gets the current system time in seconds and microseconds
 *	since the beginning of the epoch: 00:00 UCT, January 1, 1970.
 *
 * Results:
 *	Returns the current time in timePtr.
 *
 * Side effects:
 *	See NativeGetMicroseconds for more information.
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,
    ClientData clientData)
{
    Tcl_WideInt usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */
    if ( (usecSincePosixEpoch = NativeGetMicroseconds()) ) {
	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
    } else {
	/*
	* High resolution timer is not available. Just use ftime.
	*/

	struct _timeb t;

	_ftime(&t);
	timePtr->sec = (long)t.time;
	timePtr->usec = t.millitm * 1000;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * StopCalibration --
 *
 *	Turns off the calibration thread in preparation for exiting the
 *	process.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the 'exitEvent' event in the 'timeInfo' structure to ask the
 *	thread in question to exit, and waits for it to do so.
 *
 *----------------------------------------------------------------------
 */

void TclWinResetTimerResolution(void);

static void
StopCalibration(
    ClientData unused)		/* Client data is unused */
{
    SetEvent(timeInfo.exitEvent);

    /*







|
|




>
>
>
>
>
>
>
>
>
>








|
|
|






<
|
>
|
|
<
|
|












|
|

<
|
|
>
|
<
|
<
<
<
>
>
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
|
|

<
<
|
|
|
<




















<
<







421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485

486



487
488
489
490
491


492





















493







494
495
496


497
498
499

500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519


520
521
522
523
524
525
526

    if (timeInfo.perfCounterAvailable && timeInfo.curCounterFreq.QuadPart!=0) {
	/*
	 * Query the performance counter and use it to calculate the current
	 * time.
	 */

	ULARGE_INTEGER fileTimeLastCall;
	LARGE_INTEGER perfCounterLastCall, curCounterFreq;
				/* Copy with current data of calibration cycle */

	LARGE_INTEGER curCounter;
				/* Current performance counter. */
	Tcl_WideInt curFileTime;/* Current estimated time, expressed as 100-ns
				 * ticks since the Windows epoch. */
	static LARGE_INTEGER posixEpoch;
				/* Posix epoch expressed as 100-ns ticks since
				 * the windows epoch. */
	Tcl_WideInt usecSincePosixEpoch;
				/* Current microseconds since Posix epoch. */

	posixEpoch.LowPart = 0xD53E8000;
	posixEpoch.HighPart = 0x019DB1DE;

	QueryPerformanceCounter(&curCounter);

	/*
	 * Hold time section locked as short as possible
	 */
	EnterCriticalSection(&timeInfo.cs);

	fileTimeLastCall.QuadPart = timeInfo.fileTimeLastCall.QuadPart;
	perfCounterLastCall.QuadPart = timeInfo.perfCounterLastCall.QuadPart;
	curCounterFreq.QuadPart = timeInfo.curCounterFreq.QuadPart;

	LeaveCriticalSection(&timeInfo.cs);

	/*
	 * If calibration cycle occurred after we get curCounter
	 */

	if (curCounter.QuadPart <= perfCounterLastCall.QuadPart) {
	    usecSincePosixEpoch =
		(fileTimeLastCall.QuadPart - posixEpoch.QuadPart) / 10;
	    timePtr->sec = (long) (usecSincePosixEpoch / 1000000);

	    timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
	    return;
	}

	/*
	 * If it appears to be more than 1.1 seconds since the last trip
	 * through the calibration loop, the performance counter may have
	 * jumped forward. (See MSDN Knowledge Base article Q274323 for a
	 * description of the hardware problem that makes this test
	 * necessary.) If the counter jumps, we don't want to use it directly.
	 * Instead, we must return system time. Eventually, the calibration
	 * loop should recover.
	 */

	if (curCounter.QuadPart - perfCounterLastCall.QuadPart <
		11 * curCounterFreq.QuadPart / 10
	) {

	    curFileTime = fileTimeLastCall.QuadPart +
		 ((curCounter.QuadPart - perfCounterLastCall.QuadPart)
		    * 10000000 / curCounterFreq.QuadPart);


	    usecSincePosixEpoch = (curFileTime - posixEpoch.QuadPart) / 10;



	    timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	    timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
	    return;
	}
    }
























    /*







     * High resolution timer is not available. Just use ftime.
     */



    _ftime(&t);
    timePtr->sec = (long)t.time;
    timePtr->usec = t.millitm * 1000;

}

/*
 *----------------------------------------------------------------------
 *
 * StopCalibration --
 *
 *	Turns off the calibration thread in preparation for exiting the
 *	process.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the 'exitEvent' event in the 'timeInfo' structure to ask the
 *	thread in question to exit, and waits for it to do so.
 *
 *----------------------------------------------------------------------
 */



static void
StopCalibration(
    ClientData unused)		/* Client data is unused */
{
    SetEvent(timeInfo.exitEvent);

    /*
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
struct tm *
TclpGetDate(
    CONST time_t *t,
    int useGMT)
{
    struct tm *tmPtr;
    time_t time;
#if defined(_WIN64) || (defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400))
#   define  t2 *t /* no need to cripple time to 32-bit */
#else
    time_t t2 = *(__time32_t *)t;
#endif

    if (!useGMT) {
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
#	undef timezone /* prevent conflict with timezone() function */
	long timezone = 0;
#endif

	tzset();

	/*
	 * If we are in the valid range, let the C run-time library handle it.
	 * Otherwise we need to fake it. Note that this algorithm ignores
	 * daylight savings time before the epoch.
	 */







<
<
<
<
<


<
<
<
<
<







641
642
643
644
645
646
647





648
649





650
651
652
653
654
655
656
struct tm *
TclpGetDate(
    CONST time_t *t,
    int useGMT)
{
    struct tm *tmPtr;
    time_t time;






    if (!useGMT) {





	tzset();

	/*
	 * If we are in the valid range, let the C run-time library handle it.
	 * Otherwise we need to fake it. Note that this algorithm ignores
	 * daylight savings time before the epoch.
	 */
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915

#ifdef __BORLANDC__
#define LOCALTIME_VALIDITY_BOUNDARY	SECSPERDAY
#else
#define LOCALTIME_VALIDITY_BOUNDARY	0
#endif

	if (t2 >= LOCALTIME_VALIDITY_BOUNDARY) {
	    return TclpLocaltime(&t2);
	}

#if defined(_MSC_VER) && (_MSC_VER >= 1900)
	_get_timezone(&timezone);
#endif

	time = t2 - timezone;

	/*
	 * If we aren't near to overflowing the long, just add the bias and
	 * use the normal calculation. Otherwise we will need to adjust the
	 * result at the end.
	 */

	if (t2 < (LONG_MAX - 2*SECSPERDAY) && t2 > (LONG_MIN + 2*SECSPERDAY)) {
	    tmPtr = ComputeGMT(&time);
	} else {
	    tmPtr = ComputeGMT(&t2);

	    tzset();

	    /*
	     * Add the bias directly to the tm structure to avoid overflow.
	     * Propagate seconds overflow into minutes, hours and days.
	     */







|
|


<
<
<
<
|







|


|







668
669
670
671
672
673
674
675
676
677
678




679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697

#ifdef __BORLANDC__
#define LOCALTIME_VALIDITY_BOUNDARY	SECSPERDAY
#else
#define LOCALTIME_VALIDITY_BOUNDARY	0
#endif

	if (*t >= LOCALTIME_VALIDITY_BOUNDARY) {
	    return TclpLocaltime(t);
	}





	time = *t - timezone;

	/*
	 * If we aren't near to overflowing the long, just add the bias and
	 * use the normal calculation. Otherwise we will need to adjust the
	 * result at the end.
	 */

	if (*t < (LONG_MAX - 2*SECSPERDAY) && *t > (LONG_MIN + 2*SECSPERDAY)) {
	    tmPtr = ComputeGMT(&time);
	} else {
	    tmPtr = ComputeGMT(t);

	    tzset();

	    /*
	     * Add the bias directly to the tm structure to avoid overflow.
	     * Propagate seconds overflow into minutes, hours and days.
	     */
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

	    time /= 24;
	    tmPtr->tm_mday += (int)time;
	    tmPtr->tm_yday += (int)time;
	    tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7;
	}
    } else {
	tmPtr = ComputeGMT(&t2);
    }
    return tmPtr;
}

/*
 *----------------------------------------------------------------------
 *







|







719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

	    time /= 24;
	    tmPtr->tm_mday += (int)time;
	    tmPtr->tm_yday += (int)time;
	    tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7;
	}
    } else {
	tmPtr = ComputeGMT(t);
    }
    return tmPtr;
}

/*
 *----------------------------------------------------------------------
 *
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
     */

    GetSystemTimeAsFileTime(&curFileTime);
    QueryPerformanceCounter(&timeInfo.perfCounterLastCall);
    QueryPerformanceFrequency(&timeInfo.curCounterFreq);
    timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime;
    timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime;
    /* Calibrated file-time will be saved from posix in 100-ns ticks */
    timeInfo.fileTimeLastCall.QuadPart -= timeInfo.posixEpoch.QuadPart;

    ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart,
	    timeInfo.curCounterFreq.QuadPart);

    /*
     * Wake up the calling thread. When it wakes up, it will release the







<
<







879
880
881
882
883
884
885


886
887
888
889
890
891
892
     */

    GetSystemTimeAsFileTime(&curFileTime);
    QueryPerformanceCounter(&timeInfo.perfCounterLastCall);
    QueryPerformanceFrequency(&timeInfo.curCounterFreq);
    timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime;
    timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime;



    ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart,
	    timeInfo.curCounterFreq.QuadPart);

    /*
     * Wake up the calling thread. When it wakes up, it will release the
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
	waitResult = WaitForSingleObjectEx(timeInfo.exitEvent, 1000, FALSE);
	if (waitResult == WAIT_OBJECT_0) {
	    break;
	}
	UpdateTimeEachSecond();
    }


    return (DWORD) 0;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateTimeEachSecond --







>







907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
	waitResult = WaitForSingleObjectEx(timeInfo.exitEvent, 1000, FALSE);
	if (waitResult == WAIT_OBJECT_0) {
	    break;
	}
	UpdateTimeEachSecond();
    }

    /* lint */
    return (DWORD) 0;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateTimeEachSecond --
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243

1244
1245


1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
static void
UpdateTimeEachSecond(void)
{
    LARGE_INTEGER curPerfCounter;
				/* Current value returned from
				 * QueryPerformanceCounter. */
    FILETIME curSysTime;	/* Current system time. */
    static LARGE_INTEGER lastFileTime;
				/* File time of the previous calibration */
    LARGE_INTEGER curFileTime;	/* File time at the time this callback was
				 * scheduled. */
    Tcl_WideInt estFreq;	/* Estimated perf counter frequency. */
    Tcl_WideInt vt0;		/* Tcl time right now. */
    Tcl_WideInt vt1;		/* Tcl time one second from now. */
    Tcl_WideInt tdiff;		/* Difference between system clock and Tcl
				 * time. */
    Tcl_WideInt driftFreq;	/* Frequency needed to drift virtual time into
				 * step over 1 second. */

    /*
     * Sample performance counter and system time (from posix epoch).
     */


    GetSystemTimeAsFileTime(&curSysTime);
    curFileTime.LowPart = curSysTime.dwLowDateTime;
    curFileTime.HighPart = curSysTime.dwHighDateTime;
    curFileTime.QuadPart -= timeInfo.posixEpoch.QuadPart;
    /* If calibration still not needed (check for possible time switch) */
    if ( curFileTime.QuadPart > lastFileTime.QuadPart
      && curFileTime.QuadPart < lastFileTime.QuadPart +
      				    (timeInfo.calibrationInterv * 10000000)
    ) {
    	/* again in next one second */
	return;
    }
    QueryPerformanceCounter(&curPerfCounter);

    lastFileTime.QuadPart = curFileTime.QuadPart;

    /*
     * We devide by timeInfo.curCounterFreq.QuadPart in several places. That
     * value should always be positive on a correctly functioning system. But
     * it is good to be defensive about such matters. So if something goes
     * wrong and the value does goes to zero, we clear the
     * timeInfo.perfCounterAvailable in order to cause the calibration thread
     * to shut itself down, then return without additional processing.
     */

    if (timeInfo.curCounterFreq.QuadPart == 0){

	timeInfo.perfCounterAvailable = 0;
	return;
    }

    /*
     * Several things may have gone wrong here that have to be checked for.
     *  (1) The performance counter may have jumped.
     *  (2) The system clock may have been reset.
     *
     * In either case, we'll need to reinitialize the circular buffer with
     * samples relative to the current system time and the NOMINAL performance
     * frequency (not the actual, because the actual has probably run slow in
     * the first case). Our estimated frequency will be the nominal frequency.
     *
     * Store the current sample into the circular buffer of samples, and
     * estimate the performance counter frequency.
     */

     estFreq = AccumulateSample(curPerfCounter.QuadPart,
	    (Tcl_WideUInt) curFileTime.QuadPart);

    /*
     * We want to adjust things so that time appears to be continuous.
     * Virtual file time, right now, is
     *
     * vt0 = 10000000 * (curPerfCounter - perfCounterLastCall)
     *	     / curCounterFreq
     *	     + fileTimeLastCall
     *
     * Ideally, we would like to drift the clock into place over a period of 2
     * sec, so that virtual time 2 sec from now will be
     *
     * vt1 = 20000000 + curFileTime
     *
     * The frequency that we need to use to drift the counter back into place
     * is estFreq * 20000000 / (vt1 - vt0)
     */


    vt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,


	    curPerfCounter.QuadPart);
    /*
     * If we've gotten more than a second away from system time, then drifting
     * the clock is going to be pretty hopeless. Just let it jump. Otherwise,
     * compute the drift frequency and fill in everything.
     */

    tdiff = vt0 - curFileTime.QuadPart;
    if (tdiff > 10000000 || tdiff < -10000000) {
    	/* jump to current system time, use curent estimated frequency */
    	vt0 = curFileTime.QuadPart;

    } else {
    	/* calculate new frequency and estimate drift to the next second */
	vt1 = 20000000 + curFileTime.QuadPart;
	driftFreq = (estFreq * 20000000 / (vt1 - vt0));
	/*
	 * Avoid too large drifts (only half of the current difference),
	 * that allows also be more accurate (aspire to the smallest tdiff),
	 * so then we can prolong calibration interval by tdiff < 100000
	 */
	driftFreq = timeInfo.curCounterFreq.QuadPart +
		(driftFreq - timeInfo.curCounterFreq.QuadPart) / 2;

	/*
	 * Average between estimated, 2 current and 5 drifted frequencies,
	 * (do the soft drifting as possible)
	 */
	estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart + 5 * driftFreq) / 8;
    }

    /* Avoid too large discrepancy from nominal frequency */
    if (estFreq > 1003*timeInfo.nominalFreq.QuadPart/1000) {
	estFreq = 1003*timeInfo.nominalFreq.QuadPart/1000;
	vt0 = curFileTime.QuadPart;
    } else if (estFreq < 997*timeInfo.nominalFreq.QuadPart/1000) {
	estFreq = 997*timeInfo.nominalFreq.QuadPart/1000;
	vt0 = curFileTime.QuadPart;
    } else if (vt0 != curFileTime.QuadPart) {
	/*
	 * Be sure the clock ticks never backwards (avoid it by negative drifting)
	 * just compare native time (in 100-ns) before and hereafter using
	 * new calibrated values) and do a small adjustment (short time freeze)
	 */
	LARGE_INTEGER newPerfCounter;
	Tcl_WideInt nt0, nt1;

	QueryPerformanceCounter(&newPerfCounter);
	nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
		timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,
		newPerfCounter.QuadPart);
	nt1 = NativeCalc100NsTicks(vt0,
		curPerfCounter.QuadPart, estFreq,
		newPerfCounter.QuadPart);
	if (nt0 > nt1) { /* drifted backwards, try to compensate with new base */
	    /* first adjust with a micro jump (short frozen time is acceptable) */
	    vt0 += nt0 - nt1;
	    /* if drift unavoidable (e. g. we had a time switch), then reset it */
	    vt1 = vt0 - curFileTime.QuadPart;
	    if (vt1 > 10000000 || vt1 < -10000000) {
	    	/* larger jump resp. shift relative new file-time */
	    	vt0 = curFileTime.QuadPart;
	    }
	}
    }

    /* In lock commit new values to timeInfo (hold lock as short as possible) */
    EnterCriticalSection(&timeInfo.cs);

    /* grow calibration interval up to 10 seconds (if still precise enough) */
    if (tdiff < -100000 || tdiff > 100000) {
	/* too long drift - reset calibration interval to 1000 second */
	timeInfo.calibrationInterv = 1;
    } else if (timeInfo.calibrationInterv < 10) {
	timeInfo.calibrationInterv++;
    }

    timeInfo.fileTimeLastCall.QuadPart = vt0;
    timeInfo.curCounterFreq.QuadPart = estFreq;
    timeInfo.perfCounterLastCall.QuadPart = curPerfCounter.QuadPart;

    LeaveCriticalSection(&timeInfo.cs);
}

/*
 *----------------------------------------------------------------------







<
<











|


>



<
<
<
<
<
<
<
<
|
<
|
<











>


















|



















>
|
|
>
>
|








<
|
>

<
<
|
<
<
<
<
<
<
<

<
<
<
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
|
<
<
|
<
<
<
<
<
<


<
<







938
939
940
941
942
943
944


945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962








963

964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031


1032







1033






1034


1035




1036







1037















1038
1039

1040


1041






1042
1043


1044
1045
1046
1047
1048
1049
1050
static void
UpdateTimeEachSecond(void)
{
    LARGE_INTEGER curPerfCounter;
				/* Current value returned from
				 * QueryPerformanceCounter. */
    FILETIME curSysTime;	/* Current system time. */


    LARGE_INTEGER curFileTime;	/* File time at the time this callback was
				 * scheduled. */
    Tcl_WideInt estFreq;	/* Estimated perf counter frequency. */
    Tcl_WideInt vt0;		/* Tcl time right now. */
    Tcl_WideInt vt1;		/* Tcl time one second from now. */
    Tcl_WideInt tdiff;		/* Difference between system clock and Tcl
				 * time. */
    Tcl_WideInt driftFreq;	/* Frequency needed to drift virtual time into
				 * step over 1 second. */

    /*
     * Sample performance counter and system time.
     */

    QueryPerformanceCounter(&curPerfCounter);
    GetSystemTimeAsFileTime(&curSysTime);
    curFileTime.LowPart = curSysTime.dwLowDateTime;
    curFileTime.HighPart = curSysTime.dwHighDateTime;










    EnterCriticalSection(&timeInfo.cs);


    /*
     * We devide by timeInfo.curCounterFreq.QuadPart in several places. That
     * value should always be positive on a correctly functioning system. But
     * it is good to be defensive about such matters. So if something goes
     * wrong and the value does goes to zero, we clear the
     * timeInfo.perfCounterAvailable in order to cause the calibration thread
     * to shut itself down, then return without additional processing.
     */

    if (timeInfo.curCounterFreq.QuadPart == 0){
	LeaveCriticalSection(&timeInfo.cs);
	timeInfo.perfCounterAvailable = 0;
	return;
    }

    /*
     * Several things may have gone wrong here that have to be checked for.
     *  (1) The performance counter may have jumped.
     *  (2) The system clock may have been reset.
     *
     * In either case, we'll need to reinitialize the circular buffer with
     * samples relative to the current system time and the NOMINAL performance
     * frequency (not the actual, because the actual has probably run slow in
     * the first case). Our estimated frequency will be the nominal frequency.
     *
     * Store the current sample into the circular buffer of samples, and
     * estimate the performance counter frequency.
     */

    estFreq = AccumulateSample(curPerfCounter.QuadPart,
	    (Tcl_WideUInt) curFileTime.QuadPart);

    /*
     * We want to adjust things so that time appears to be continuous.
     * Virtual file time, right now, is
     *
     * vt0 = 10000000 * (curPerfCounter - perfCounterLastCall)
     *	     / curCounterFreq
     *	     + fileTimeLastCall
     *
     * Ideally, we would like to drift the clock into place over a period of 2
     * sec, so that virtual time 2 sec from now will be
     *
     * vt1 = 20000000 + curFileTime
     *
     * The frequency that we need to use to drift the counter back into place
     * is estFreq * 20000000 / (vt1 - vt0)
     */

    vt0 = 10000000 * (curPerfCounter.QuadPart
		- timeInfo.perfCounterLastCall.QuadPart)
	    / timeInfo.curCounterFreq.QuadPart
	    + timeInfo.fileTimeLastCall.QuadPart;
    vt1 = 20000000 + curFileTime.QuadPart;

    /*
     * If we've gotten more than a second away from system time, then drifting
     * the clock is going to be pretty hopeless. Just let it jump. Otherwise,
     * compute the drift frequency and fill in everything.
     */

    tdiff = vt0 - curFileTime.QuadPart;
    if (tdiff > 10000000 || tdiff < -10000000) {

	timeInfo.fileTimeLastCall.QuadPart = curFileTime.QuadPart;
	timeInfo.curCounterFreq.QuadPart = estFreq;
    } else {


	driftFreq = estFreq * 20000000 / (vt1 - vt0);














	if (driftFreq > 1003*estFreq/1000) {


	    driftFreq = 1003*estFreq/1000;




	} else if (driftFreq < 997*estFreq/1000) {







	    driftFreq = 997*estFreq/1000;















	}


	timeInfo.fileTimeLastCall.QuadPart = vt0;


	timeInfo.curCounterFreq.QuadPart = driftFreq;






    }



    timeInfo.perfCounterLastCall.QuadPart = curPerfCounter.QuadPart;

    LeaveCriticalSection(&timeInfo.cs);
}

/*
 *----------------------------------------------------------------------
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
{
    /*
     * The MS implementation of gmtime is thread safe because it returns the
     * time in a block of thread-local storage, and Windows does not provide a
     * Posix gmtime_r function.
     */

#if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400)
    return gmtime(timePtr);
#else
    return _gmtime32((CONST __time32_t *)timePtr);
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclpLocaltime --
 *







<

<
<
<







1191
1192
1193
1194
1195
1196
1197

1198



1199
1200
1201
1202
1203
1204
1205
{
    /*
     * The MS implementation of gmtime is thread safe because it returns the
     * time in a block of thread-local storage, and Windows does not provide a
     * Posix gmtime_r function.
     */


    return gmtime(timePtr);



}

/*
 *----------------------------------------------------------------------
 *
 * TclpLocaltime --
 *
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
{
    /*
     * The MS implementation of localtime is thread safe because it returns
     * the time in a block of thread-local storage, and Windows does not
     * provide a Posix localtime_r function.
     */

#if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400)
    return localtime(timePtr);
#else
    return _localtime32((CONST __time32_t *)timePtr);
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimeProc --
 *







<

<
<
<







1223
1224
1225
1226
1227
1228
1229

1230



1231
1232
1233
1234
1235
1236
1237
{
    /*
     * The MS implementation of localtime is thread safe because it returns
     * the time in a block of thread-local storage, and Windows does not
     * provide a Posix localtime_r function.
     */


    return localtime(timePtr);



}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimeProc --
 *